使用boost :: python将C++类实例传递给python

Emi*_*ano 13 c++ python boost boost-python

我有一个库创建对象(类A的实例)并将它们传递给python程序,该程序应该能够调用它们的方法.

基本上我有C++类实例,我想从python中使用它们.有时,该对象应该传递回C++进行一些操作.

我创建了以下包装器文件(假设该New函数在C++代码中的某处调用):

#include <boost/python.hpp>
#include <iostream>
#include <boost/smart_ptr.hpp>

using namespace boost;
using namespace boost::python;

int calls = 0;

struct A
{
   int f() { return calls++; }
   ~A() { std::cout << "destroyed\n"; }
};

shared_ptr<A> existing_instance;

void New() { existing_instance = shared_ptr<A>( new A() ); }

int Count( shared_ptr<A> a ) { return a.use_count(); }

BOOST_PYTHON_MODULE(libp)
{
    class_<A>("A")
        .def("f", &A::f)
    ;

    def("Count", &Count);

    register_ptr_to_python< shared_ptr<A> >();
} 
Run Code Online (Sandbox Code Playgroud)

代码缺少python获取的部分existing_instance.我没有粘贴它,但我只是说我为此目的使用回调机制.

这段代码有效,但我有几个问题:

  1. 在Count函数(以及所有其他C++操作函数中)可以这样传递a或者更好地做类似的事情const shared_ptr<A>&吗?在我在python boost文档中找到的代码片段中经常使用引用,但我不理解其中的区别(当然,除了有更高的引用计数器).

  2. 这段代码"安全"吗?当我将existing_instance传递给python时,它的计数器将递增(只有一次,即使在python中我制作了更多的对象副本,当然)所以C++代码没有办法可以破坏对象,就像python一样至少是一个"副本".我对么?我试着用指针玩,看来我是对的,我只想确定一下.

  3. 我想阻止python创建A的实例.它们只能从C++代码传递.我怎么能实现这一目标?编辑:发现,我只需要使用no_init和noncopyable:class_<A, boost::noncopyable>("A", no_init)

Jam*_*mes 14

boost::python知道所有boost::shared_ptr,但你需要告诉它boost::shared_ptr<A>有一个实例A,你通过添加boost::shared_ptr<A>模板参数列表来做到这一点,class_关于这个'Held Type'的更多信息在boost文档中.

为了防止从python创建实例,你添加boost::python::no_init到class_构造函数,所以最终得到:

boost::python::class_< A, boost::shared_ptr<A> >("A", boost::python::no_init)
    //... .def, etc
    ;
Run Code Online (Sandbox Code Playgroud)

一般你不应该通过引用传递围绕共享指针,因为如果到共享指针引用无效,则引用到的共享指针指向也是无效的(因为服用共享指针的引用未增加指向对象的引用计数器).

boost::shared_ptr对象传递给python和从python 传出是完全安全的,只要你不改变引用计数,引用计数(python和shared_ptr)就会被正确管理return_value_policy.如果你更改python中公开的方法的策略,以便它返回对共享指针的引用,那么你可能会导致问题,就像通过c ++引用传递共享指针可能会导致问题一样.

(另外,你应该make_shared<A>(...)优先使用shared_ptr<A>(new A(...)).)