5

我想知道是否有任何方法可以将 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*,以便将其作为参数(args)发送到例如 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 来做到这一点的方法。

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

4

2 回答 2

6

据我所知,没有简单的方法可以做到这一点。

要使用 C++ 扩展 Python,既没有模块也没有中间库,需要动态加载库,然后导入函数。模块使用这种方法ctypes。要使用 C++ 完成相同的任务,需要编写一个ctypes类库,该库理解目标编译器的 C++ ABI。

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

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

于 2013-08-26T17:57:36.937 回答
1

我找到了我的答案。实际上,我正在搜索的内容与此答案非常相似(感谢 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 暴露:

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) 指向我的类的实例
于 2013-08-28T16:23:06.763 回答