将派生类型的对象从 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&lt;Derived&gt; 可以解决此问题,因此我知道Boost.Python 在内部使用shared_ptrs 管理对象。我还需要做些什么来让 Boost.Python 意识到可以将 shared_ptr&lt;Derived&gt; 传递给期望 shared_ptr&lt;Base&gt; 的函数吗?

【问题讨论】:

【参考方案1】:

Boost.Python 需要知道指向Derived 的智能指针可以转换为指向AbstractBase 的智能指针。这可以通过以下任一方式完成:

使用boost::shared_ptr。当 element_type 是分层的时,Boost.Python 有代码来处理 boost::shared_ptrs 之间的隐式转换。

通过boost::python::implicitly_convertible 注册从std::shared_ptr&lt;Derived&gt;std::shared_ptr&lt;AbstractBase&gt; 的隐式转换。 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 传递给基类型的主要内容,如果未能解决你的问题,请参考以下文章

将派生类传递给采用 SWIG Python 中的基类的函数

C++ 类型将基础对象转换为派生对象

如何将对象列表从 C++ 传递到 C#?

将图像从 python 包装器传递给 c++ 函数

在 C++ 中将派生类类型的向量链接到父类类型的向量

C++入门到精通:面向对象程序设计中的继承与派生!