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

すべて正常に動作し、通話Print callからのテキストがありProcessFooます。しかし、渡されたすべてのポインターを次のように保存したいProcessFoo:

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

関数ポインターの終了後、無効になり、ベクターから使用できなくなります。そのポインターの寿命を長くする最良の方法は何ですか? 共有ポインタを使用するか、Python にオブジェクトを削除しないように指示します (削除する場合は?)

4

1 に答える 1

2

このポインターを保存する場合は、基になる Python オブジェクト (PyObject) の参照カウントをインクリメントする必要があります。このためには、void ProcessFoo(Foo *obj) を実装して、C++ オブジェクトの代わりに python オブジェクトを取得する必要があります。そうしないと、boost::python が適応で 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 ) );
}
于 2012-09-08T10:25:22.030 に答える