2011-11-17 35 views
6

Tôi đang sử dụng Boost.Python để tạo trình bao bọc cho thư viện C++ của mình và tôi gặp một số vấn đề, googling cả ngày không tạo ra bất kỳ kết quả nào. Ví dụ, tôi có đoạn mã sau:Boost.Python và C++ std :: vectơ của con trỏ

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>()); 
} 

Vì vậy, tôi biên dịch nó, nhập khẩu trong python và thử điều này:

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

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

dòng đầu tiên, như mong đợi, ném một ngoại lệ nói rằng b.func() là tinh khiết ảo, và dòng thứ hai in ra

0.123.

Derived :: func()

Và đó là ok.

Nhưng mã

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

không làm việc, và Python ném một ngoại lệ:

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

Tại sao nó xử lý một cách chính xác cơ sở * trả về bởi makeDerived() và từ chối làm việc với cơ sở * chứa trong std :: vector? Làm thế nào tôi có thể làm cho nó hoạt động?

Trả lời

3

Bạn có thể khắc phục điều này bằng cách đăng ký Base* như một loại có thể được sử dụng để trỏ đến một BaseWrapper*:

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

Nhưng có vẻ như điều này có nghĩa rằng Base không thể có một chức năng ảo tinh khiết ...

+0

Đúng, làm cho Base :: func() không giải quyết được vấn đề. Cảm ơn, ít nhất là cho giải pháp này. Nhưng có một số cách giải quyết không thay đổi bất kỳ API hiện tại nào không? –

+0

Nó không chỉ làm cho nó không tinh khiết mà giải quyết vấn đề mặc dù, nó cũng đăng ký 'Base *' như là một loại con trỏ để BaseWrapper, trừ khi tôi là nhầm lẫn? Có lẽ có một cách để ép buộc python vào chấp nhận kiểu với các phương thức ảo thuần túy như kiểu con trỏ ... – James

+0

Vâng, ý tôi là làm cho func() không thuần khiết và đăng ký Base * ptr đã giải quyết được vấn đề. Bạn có thể giải thích tốt hơn làm thế nào tôi có thể làm cho python chấp nhận một loại với ảo tinh khiết? –

Các vấn đề liên quan