2011-11-17 73 views
6

我正在使用Boost.Python爲我的C++庫創建一個包裝器,而且我遇到了一些麻煩,一整天都沒有產生任何結果。例如,我有以下代碼:Boost.Python和C++ std ::指針向量

class Base 
{ 
public: 
    virtual void func() = 0; 
}; 

class Derived : public Base 
{ 
public: 
    virtual void func() 
    { 
     cout << "Derived::func()"<< endl; 
    } 
}; 


// wrapper for Base 
struct BaseWrapper : Base, python::wrapper<Base> 
{ 
    virtual void func() 
    { 
     this->get_override("func"); 
    } 
}; 


Base* makeDerived() 
{ 
    return new Derived; 
} 

vector<Base*>* makeDerivedVec() 
{ 
    vector<Base*> *v = new vector<Base*>; 
    v->push_back(new Derived); 
    v->push_back(new Derived); 
    v->push_back(new Derived); 
    return v; 
} 

BOOST_PYTHON_MODULE(mylib) 
{ 
    // export Base 
    class_<BaseWrapper, noncopyable>("Base") 
      .def("func", pure_virtual(&Base::func)); 

    class_<vector<Base*> >("BasePtrVec") 
      .def(vector_indexing_suite<vector<Base*> >()); 

    // export Derived 
    class_<Derived, bases<Base> >("Derived") 
      .def("func", &Derived::func); 

    // export makeDerived() 
    def("makeDerived", &makeDerived, return_value_policy<manage_new_object>()); 

    // export makeDerivedVec() 
    def("makeDerivedVec", &makeDerivedVec, return_value_policy<manage_new_object>()); 
} 

所以,我編譯它,進口在Python和嘗試這個辦法:

B = mylib.Base()b.func()

d = mylib.makeDerived()d.func()

第一行,如所預期,拋出異常說b.func()是純虛擬的,並且所述第二線打印出

衍生:: FUNC()

這是很正常的。

但代碼

dlist = mylib.makeDerivedVec() 
for d in dlist: 
    d.func() 

不工作,和Python會拋出異常:

TypeError: No to_python (by-value) converter found for C++ type: Base* 

爲什麼正確處理基礎*通過makeDerived(返回),並拒絕與基地工作*包含在std :: vector中?我怎樣才能使它工作?

回答

3

您可以通過註冊Base*作爲可用於指向一個BaseWrapper*一種解決這個問題:

class_<BaseWrapper, noncopyable, Base*>("Base") 
     .def("func", pure_virtual(&Base::func)); 

但似乎這意味着Base不能有一個純虛函數...

+0

是的,使Base :: func()不是純粹的解決了這個問題。謝謝,至少對於這個解決方案。但有沒有一些解決方法不會改變任何現有的API? –

+0

這不僅僅是使它不是純粹的解決問題,它還將'Base *'註冊爲BaseWrapper的指針類型,除非我錯了?也許有一種方法來強制增強python接受一個類型的純虛擬方法作爲指針類型... – James

+0

是的,我的意思是讓func()不純並且註冊Base * ptr解決了這個問題。你能更好地解釋我如何讓python接受純虛擬類型? –