如何在不构建模块的情况下向Python公开C ++类

发布于 2021-01-29 14:56:26

我想知道是否有任何方法可以将C ++类公开给Python,但无需构建中间共享库。

这是我理想的情况。例如,我有以下C ++类:

class toto
     {
     public:
        toto(int iValue1_, int iValue2_): iValue1(iValue1_), iValue2(iValue2_) {}
        int Addition(void) const {if (!this) return 0; return iValue1 + iValue2;}

      private:
        int iValue1;
        int iValue2;
     };

我想以某种方式将此类(或其实例)转换为PyObject *,以便将其作为参数(参数)发送给例如PyObject_CallObject:

PyObject* PyObject_CallObject(PyObject* wrapperFunction, PyObject* args)

另一方面,在python端,我有一个wrapperFunction,它将我的C ++类(或其实例)上的指针作为参数,并调用其方法或使用其属性:

def wrapper_function(cPlusPlusClass):
    instance = cPlusPlusClass(4, 5)
    result = instance.Addition()

如您所见,我并不需要/不想拥有单独的共享库或通过boost python构建模块。我需要做的就是找到一种将C
++代码转换为PyObject并将其发送给python的方法。我找不到通过C python库,boost或SWIG做到这一点的方法。

你有什么主意吗?谢谢你的帮助。

关注者
0
被浏览
111
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我找到了答案。实际上,我正在搜索的内容与此答案非常相似(感谢moooeeeep的评论):

    将C
    ++类实例暴露给python嵌入式解释器

    遵循C ++类(注意!默认构造函数是必需的):

    class TwoValues
    {
    public:
        TwoValues(void): iValue1(0), iValue2(0) {}
        TwoValues(int iValue1, int iValue2): iValue1(iValue1_), iValue2(iValue2_) {}
    
        int Addition(void) const {if (!this) return 0; return iValue1 + iValue2;}
    
    public:
        int iValue1;
        int iValue2;
    };
    

    可以通过以下宏通过增强来暴露:

    BOOST_PYTHON_MODULE(ModuleTestBoost)
    {
    class_<TwoValues>("TwoValues")
       .def("Addition",             &TWOVALUES::Addition)
       .add_property("Value1",      &TWOVALUES::iValue1)
       .add_property("Value2",      &TWOVALUES::iValue2);
    };
    

    另一方面,我定义了一个python函数,python_script.py该函数接受此类的实例并执行某些操作。例如:

    def wrapper_function(instance):
        result = instance.Addition()
        myfile = open(r"C:\...\testboostexample.txt", "w")
        output = 'First variable is {0}, second variable is {1} and finally the addition is {2}'.format(instance.Value1, instance.Value2, result)
        myfile .write(output)
        myfile .close()
    

    然后在C ++端,我可以通过同时发送类的实例来调用此函数,如下所示:

    Py_Initialize();
    
    try
        {
        TwoValues instance(5, 10);
        initModuleTestBoost();
    
        object python_script = import("python_script");
        object wrapper_function = python_script.attr("wrapper_function");
        wrapper_function(&instance);
        }
    catch (error_already_set)
        {
        PyErr_Print();
        }
    
    Py_Finalize();
    

    优点:

    • 我不需要建立任何共享库或二进制文件
    • 当我使用Boost时,我不必担心内存管理和引用计数
    • 我不使用共享的升压指针(boost :: shared_ptr)指向类的实例


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看