2013-08-26 31 views
5

我想知道是否有任何方法将C++类暴露给Python,但没有构建中间共享库。如何在不构建模块的情况下将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; 
    }; 

我想以某种方式转换这个类(或其intance)到的PyObject *,以将其作为paremter(参数)到例如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来实现的方法。

你有什么想法吗? 感谢您的帮助。

+1

的 情况下,我不知道我知道你想要什么。 Boost.Python有'boost :: python :: object :: ptr',它返回一个'PyObject *' - 这是你在找什么? –

+1

我相信可以通过'ctypes'访问C/C++,但是暴露一个C++类可能是一件困难的事情。 – Bakuriu

+0

@PaulManta:谢谢你的回答。我想要的包括3个步骤:第1步:在PyObject指针中封装一个C++类。步骤2将此指针发送给一个python函数。第三步。在python中使用这个C++指针(即调用它的方法)。所以,你可以请更实用,并告诉通过一个例子如何封装C++代码到object :: ptr? –

回答

1

我找到了我的答案。其实我在寻找是相当类似这样的回答(为他的评论感谢moooeeeep):

Exposing a C++ class instance to a python embedded interpreter

下面的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_script.py WHI定义的Python函数ch需要这个类的一个实例并做一些事情。例如:

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,我不需要担心内存管理 &引用计数
  • 我不使用共享升压指针(升压:: shared_ptr的)指向我的课
6

据我所知,有没有简单的方法来实现这一点。要使用C++扩展Python既不需要模块,也不需要中间库,它需要动态加载库,然后导入函数。 ctypes模块使用此方法。为了实现与C++相同的功能,需要编写一个类似于的库来理解目标编译器的C++ ABI。

要在不引入模块的情况下扩展Python,可以创建一个提供包装C++库的C API的中间库。这个中间库然后可以通过​​在Python中使用。尽管它没有提供确切的调用语法,并且引入了一个中间库,但它可能比构建一个类似于的库更省力,它可以直接与C++接口。

但是,如果要引入中间库,则可能需要使用Boost.Python,SWIG或其他一些C++/Python语言绑定工具。虽然这些工具中的很多都会通过模块引入扩展,但它们通常会提供更清晰的调用约定,在绑定过程中更好地进行错误检查,并且可能更易于维护。

+0

非常好的答案。涵盖了我想说的一切和更多(所以我甚至不会回答;) – nneonneo

相关问题