是否可以在C++程序中创建Python模块中定义的类的实例

Is it possible to create instance in C++ program of a class defined in Python module?

本文关键字:定义 模块 实例 Python 创建 C++ 程序 是否      更新时间:2023-10-16

我要做的是在C++程序中创建一个虚拟类(ClassTest),然后在Python脚本中导入它,在该脚本中创建派生类,然后在C++中导入该派生类。

这是我迄今为止想出的代码:

#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;
using namespace std;
class ClassTest {
public:
    ClassTest () {}
    virtual int someFunction () = 0;
};
BOOST_PYTHON_MODULE(ClassTest) {
    class_< ClassTest, boost::noncopyable >("ClassTest", no_init)
        .def("someFunction", &ClassTest::someFunction)
    ;
}
int main() {
    try {
        Py_Initialize();
        initClassTest();
        ClassTest* testObject = **???**
        cout << "Function result = " << testObject.someFunction() << endl;
        Py_Finalize();
    } catch (error_already_set& e) {
        PyErr_PrintEx(0);
        return 1;
    }
    return 0;
}

还有Python脚本:

import ClassTest
class classTestChild(ClassTest.ClassTest):
    def someFunction ():
        return 4;

以下是如何做到这一点的完整示例。您需要一个包装器类,以便可以在Python中重写虚拟函数。

ClassTest.h:

class ClassTest 
{
public:
    virtual ~ClassTest(){}
    virtual int someFunction () = 0;
};

ClassTest.cpp(必须内置到.so/.dll中):

class ClassTestWrap : public ClassTest, public python::wrapper<ClassTest>
{
public:
    virtual int someFunction() override
    {
        if (python::override f = this->get_override("someFunction"))
            return f();
        return ClassTestWrap::someFunction();
    }
};
BOOST_PYTHON_MODULE(ClassTest)
{
    python::class_< ClassTestWrap, boost::noncopyable >("ClassTest")
    .def("someFunction", python::pure_virtual(&ClassTestWrap::someFunction));
}

main.cpp(可执行文件):

try
{
    Py_Initialize();
    python::object main = python::import("__main__");
    python::object global(main.attr("__dict__"));
    python::object ignored = python::exec("import ClassTestn"
                                          "class classTestChild(ClassTest.ClassTest):n"
                                          "    def someFunction(self):n"
                                          "        return 4n"
                                          "n"
                                          "child = classTestChild()", global);
    ClassTest *obj = python::extract<ClassTest*>(global["child"]);
    int value = obj->someFunction();
    printf("value = %dn", value);
    Py_Finalize();
}
catch (python::error_already_set&)
{
    PyErr_Print();
    PyErr_Clear();
}

输出:

value = 4

如果ClassTest.so/ClassTest.dll和.exe在同一文件夹中,并且从同一文件夹(./test.exe)调用.exe,则此示例将起作用。