2012-07-20 2 views
4

CPP :부스트 파이썬 개체 수명

#include <boost/python.hpp> 

using namespace boost; 
using namespace boost::python; 

struct Foo 
{ 
    virtual ~Foo() {} 
    virtual void Print() = 0; 
}; 

struct FooWrap : Foo, wrapper<Foo> 
{ 
    void Print() 
    { 
     this->get_override("Print")(); 
    } 
}; 

void ProcessFoo(Foo *obj) { obj->Print(); } 

BOOST_PYTHON_MODULE(hello_ext) 
{ 
    class_<FooWrap, boost::noncopyable>("Foo") 
     .def("Print", pure_virtual(&Foo::Print)); 
    def("ProcessFoo", &ProcessFoo); 
} 

파이썬 :

import hello_ext 

class NewFoo(hello_ext.Foo): 
    def Print(self): 
     print 'Print call' 

hello_ext.ProcessFoo(NewFoo()) 

모든 것이 잘 작동 ProcessFoo 전화에서 Print call 텍스트가. 하지만 ProcessFoo 등을 모두 통과 포인터를 저장할 : 함수 포인터를 종료가 무효가 나는 벡터에서 사용할 수 없습니다

std::vector<Foo*> data; 
void ProcessFoo(Foo *obj) { data.push_back(obj); obj->Print(); } 

후. 포인터의 수명을 늘리는 가장 좋은 방법은 무엇입니까? 공유 포인터를 사용하거나 python이 객체를 삭제하지 않는다고 알려주십시오. (삭제 한 경우)

답변

2

이 포인터를 저장하려면 Python 객체 (PyObject)의 참조 횟수를 증가시켜야합니다. 이를 위해 void (void) ProcessFoo (Foo * obj)를 구현하여 C++ 객체가 아닌 python 객체를 가져와야합니다. 그렇지 않으면 boost :: python이 자신의 adaption에서 python 객체를 제거하고 더 이상 그 수명을 제어 할 수 없기 때문입니다.

이 작업을 수행하는 경우 C++로 명시 적으로 변환해야합니다 (그러나 boost :: python을 사용하면 문제가 많지 않음).

using namespace boost::python; 
std::vector< std::pair<object, Foo&> > myVec; 

void ProcessFoo(object o) 
{ 
    Foo& x = extract<Foo&>(o); 
    // ... do you add to container here, but remember, to add the object o 
    // too, otherwise the refernce counter will be decremented and the object 
    // may go away. 
    myVec.push_back(std::make_pair(o, x)); 
} 
+0

'std :: pair'에'Foo &'를 사용할 수 있습니까? –

+0

네, 가질 수 있습니다. 그것은 "포인터"이상입니다. 그러나 참조 (객체)를 증가시키고 저장함으로써 삭제 후에 객체가 액세스되지 않도록해야합니다. – Sven

관련 문제