2015-06-21 47 views
0

我想要做的是在C++程序中創建一個虛擬類(ClassTest),然後在Python腳本中導入它,在該腳本中創建派生類,然後將該派生類導回到C++中。是否可以在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; 

回答

0

下面是完整的例子,如何可以做到這一點。你需要一個包裝類,以便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 ClassTest\n" 
              "class classTestChild(ClassTest.ClassTest):\n" 
              " def someFunction(self):\n" 
              "  return 4\n" 
              "\n" 
              "child = classTestChild()", global); 
    ClassTest *obj = python::extract<ClassTest*>(global["child"]); 
    int value = obj->someFunction(); 
    printf("value = %d\n", value); 
    Py_Finalize(); 
} 
catch (python::error_already_set&) 
{ 
    PyErr_Print(); 
    PyErr_Clear(); 
} 

並輸出:

value = 4 

這個例子將工作,如果ClassTest.so/ClassTest.dll和.exe是在同一文件夾和.exe正在從相同的文件夾中稱爲(./test.exe)

+0

得到了一個錯誤: 「回溯(最後最近一次調用): 文件「」,1號線,在 導入錯誤:沒有模塊名爲ClassTest」 我嘗試別的東西,並得到了錯誤‘NameError:名字‘ClassTestChild’沒有定義’,你可以在這裏看到我的代碼:http://pastebin.com/vp3S3mqR – Jenzorek

+0

我更新了我的答案,您需要將python模塊構建成.so/.dll並將程序測試成.exe – doqtor

+0

嗯,我添加了initC lassTest();在Py_Initialize()之後;並得到另一個錯誤:「RuntimeError:這個類不能從Python實例化」。 爲什麼要.so?這不應該和靜態編譯和運行沒有什麼不同嗎? – Jenzorek

相關問題