将派生类型的对象从 python 传递到 C++ 函数时会出现 Boost Python 运行时错误,该函数期望将 shared_ptr 传递给基类型
Posted
技术标签:
【中文标题】将派生类型的对象从 python 传递到 C++ 函数时会出现 Boost Python 运行时错误,该函数期望将 shared_ptr 传递给基类型【英文标题】:Boost Python Runtime error when passing object of derived type from python to C++ function expecting a shared_ptr to base type 【发布时间】:2013-05-31 08:55:40 【问题描述】:我有一个接受 std::shared_ptr 的函数,我想从 python 将 Derived 类型的对象传递给这个函数。这是我的类定义:
struct AbstractBase
virtual void foo() = 0;
;
struct Derived : public AbstractBase
virtual void foo()
std::cout<<"Derived's foo!"<<std::endl;
;
struct Unrelated
void bar(std::shared_ptr<AbstractBase> base_shared_ptr)
base_shared_ptr->foo();
;
#endif /* CLASSES_H */
一个简单的纯 C++ 示例可以满足我的要求:
int main()
std::shared_ptr<Derived> d(new Derived);
Unrelated u;
u.bar(d);
输出:Derived's foo!
这是我的 Boost.Python Wrapper 代码:
#include <boost/python.hpp>
#include "classes.h"
BOOST_PYTHON_MODULE(shared_ptr_test)
using namespace boost::python;
class_<AbstractBase,std::shared_ptr<AbstractBase>,boost::noncopyable>("AbstractBase",no_init);
class_<Derived,std::shared_ptr<Derived>,bases<AbstractBase>,boost::noncopyable>("Derived");
class_<Unrelated,std::shared_ptr<Unrelated>,boost::noncopyable>("Unrelated")
.def("bar",&Unrelated::bar);
这是我的简单 python 测试:
import shared_ptr_test
d=shared_ptr_test.Derived()
u=shared_ptr_test.Unrelated()
u.bar(d)
令我沮丧的是,这不起作用。它编译得很好,但是当我运行 python 脚本时,我得到了这个错误:
Traceback (most recent call last):
File "test.py", line 5, in <module>
u.bar(d)
Boost.Python.ArgumentError: Python argument types in
Unrelated.bar(Unrelated, Derived)
did not match C++ signature:
bar(Unrelated lvalue, std::shared_ptr<AbstractBase>)
将bar
更改为shared_ptr<Derived>
可以解决此问题,因此我知道Boost.Python 在内部使用shared_ptr
s 管理对象。我还需要做些什么来让 Boost.Python 意识到可以将 shared_ptr<Derived>
传递给期望 shared_ptr<Base>
的函数吗?
【问题讨论】:
【参考方案1】:Boost.Python 需要知道指向Derived
的智能指针可以转换为指向AbstractBase
的智能指针。这可以通过以下任一方式完成:
boost::shared_ptr
。当 element_type
是分层的时,Boost.Python 有代码来处理 boost::shared_ptr
s 之间的隐式转换。
通过boost::python::implicitly_convertible
注册从std::shared_ptr<Derived>
到std::shared_ptr<AbstractBase>
的隐式转换。 std::shared_ptr
满足implicitly_convertible
的概念要求,所以只需要在模块定义中注册转换即可:
implicitly_convertible<std::shared_ptr<Derived>, // Source
std::shared_ptr<AbstractBase> >(); // Target
【讨论】:
好吧,这有点令人沮丧!我认为任何适用于boost::shared_ptr
的东西都适用于std::shared_ptr
,但我想这只是我们都必须处理的边缘情况之一,直到一切都很好并融入 C++11 以上是关于将派生类型的对象从 python 传递到 C++ 函数时会出现 Boost Python 运行时错误,该函数期望将 shared_ptr 传递给基类型的主要内容,如果未能解决你的问题,请参考以下文章