助推.Python未能解析传递给函数的派生类型
Boost.Python failing to resolve derived type passed to function
我在Boost中遇到了另一个障碍。Python冒险。
我定义了以下Python模块:
#include <Python.h>
#include <iostream>
#include <boost/python.hpp>
using namespace boost;
using namespace boost::python;
struct Base { };
void foo(boost::shared_ptr<Base>)
{
std::cout << "yayn";
}
BOOST_PYTHON_MODULE(Test)
{
class_<Base, shared_ptr<Base>, noncopyable>("Base", init<>());
def("foo", foo);
}
运行以下脚本:
from Test import *
class Bar(Base):
def __init__(self):
pass
foo(Base()) #works
foo(Bar()) #error
最后一行产生了一个错误,其影响如下:
Python argument types in
foo(Bar)
did not match C++ signature:
foo(class boost::shared_ptr<struct Base>)
现在我的问题是,为什么这不起作用?类型系统应该能够计算出Bar
是Base
实例吗?
http://coliru.stacked-crooked.com/a/43f111fb3032a20a
感谢您的帮助!
在这种特殊情况下,错误消息具有误导性。函数接收一个参数,该参数的类型为;但是,该参数有一个不合适的值。Bar
初始值设定项未初始化其层次结构的PythonBase
部分。Python实例不包含boost::shared_ptr<Base>
实例,从而导致Boost。Python未能调度到C++函数:
class Bar(Base):
def __init__(self):
pass # Base is not initialized.
fun(Base()) # No boost::shared_ptr<Base> instance.
要解决此问题,请在Bar.__init__()
:中显式调用Base.__init__()
class Bar(Base):
def __init__(self):
Base.__init__(self) # Instantiates boost::shared_ptr<Base>.
fun(Bar()) # Boost.Python will extract boost::shared_ptr<Base> from Bar().
有关详细信息,在Python中,如果派生类定义了__init__()
方法,那么它应该显式调用父类的__init__()
方法。Python文档指出:
如果基类有
__init__()
方法,则派生类的__init__()
方法(如果有)必须显式调用它,以确保实例的基类部分正确初始化;例如:CCD_ 12。
在Boost中。Python、C++类包装器有一个instance_holder
。这些对象在其Python对象包装器中包含C++实例,C++对象的实例化发生在Python对象的__init__
函数中:
当一个封装C++类的
__init__
函数被调用时,一个新的instance_holder
实例被创建并安装在Python对象中〔…〕
因此,如果不调用Python对象的__init__()
方法,则不会实例化内部C++对象。当从Python调用公开的C++函数时,Boost。Python将检查调用参数,试图在一组公开的函数中识别匹配的C++函数。当找不到匹配项时,它将引发一个Boost.Python.ArgumentError
异常,列出无法匹配的参数类型和C++函数集。
这里有一个完整的例子,演示了从一个公开的C++类型继承两种不同的Python类型,其中一个层次结构正确初始化,另一个没有:
#include <boost/python.hpp>
struct base {};
void foo(boost::shared_ptr<base>) {}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<base, boost::shared_ptr<base>, boost::noncopyable>(
"Base", python::init<>())
;
python::def("foo", &foo);
}
交互式使用:
>>> import example
>>> class GoodDerived(example.Base):
... def __init__(self):
... example.Base.__init__(self)
...
>>> class BadDerived(example.Base):
... def __init__(self):
... pass
...
>>> assert(isinstance(GoodDerived(), example.Base))
>>> assert(isinstance(BadDerived(), example.Base))
>>> try:
... example.foo(GoodDerived())
... got_exception = False
... except:
... got_exception = True
... finally:
... assert(not got_exception)
...
>>> try:
... example.foo(BadDerived())
... got_exception = False
... except:
... got_exception = True
... finally:
... assert(got_exception)
请注意,虽然类型层次结构是正确的,并且可以通过isinstance(()
进行验证,但类型不会指示实例是否具有适当的值。
- 为什么使用 "this" 指针调用派生成员函数?
- 在派生函数中指定void*参数
- 如何通过派生类函数更改基类中的向量
- 如何委托派生类使用其父构造函数?
- 如何使用单独文件中的派生类访问友元函数对象
- 使用基类指针创建对象时,缺少派生类析构函数
- 在 C++ 中用派生类型重写成员函数
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如果基类包含双指针成员,则派生类的构造函数
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 在派生类中绑定非静态模板化成员函数
- 使用 std::variant<...时调用 BaseState 函数而不是派生函数>
- C++:为什么无法在派生类中访问受保护的构造函数?
- C++派生的类构造函数
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 覆盖虚拟函数 - 派生类具有不同的参数
- 正在调用基方法,而不是从构造函数派生方法
- 从具有相同虚拟函数的父函数派生时如何调用子函数
- 从派生类对象调用基类函数.派生类构造函数中设置的基类数据成员