2012-07-20 115 views
4

CPP:升压Python对象生命周期

#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 ProcessFoo(Foo * obj)来获得一个python对象而不是C++对象,因为否则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

你有'Foo&'在'std :: pair'吗? – 2016-03-15 19:56:24

+0

是的,你可以拥有。它不过是一个“指针”。但是您必须确保在删除后不访问对象,这是通过增加和存储引用(对象)来确保的。 – Sven 2016-03-16 09:06:32