boost.python:参数类型与C++签名不匹配
boost.python: Argument types did not match C++ signature
我在python中调用C++函数时遇到了一个奇怪的问题。
我公开了一个类,我想从中调用一个函数:
class_<MyClass, std::shared_ptr<MyClass>>("MyClass", init<>())
// ...
.def("someFunc", &MyClass::someFunc)
;
我从通过.def_readonly(...)
公开的另一个类的成员变量中获得std::shared_ptr<MyClass>
当我尝试调用该函数时,我得到以下错误:
File "pytest.py", line 27, in test_func
cu.someFunc("string")
Boost.Python.ArgumentError: Python argument types in
MyClass.someFunc(MyClass, str)
did not match C++ signature:
result(MyClass{lvalue}, std::string)
据我所见,签名确实匹配。有人看到问题了吗?
如此票证中所跟踪的,Boost。Python并不完全支持std::shared_ptr
。
简而言之,有两种简单的解决方案:
- 使用
boost::shared_ptr
而不是std::shared_ptr
- 通过
add_property()
暴露具有的std::shared_ptr
成员变量,从而提供类型为boost::python::return_by_value
的boost::python::return_value_policy
虽然异常中的签名看起来相同,但微妙的细节是PythonMyClass
对象嵌入了一个std::shared_ptr<MyClass>
。因此,Boost。Python必须执行从std::shared_ptr<MyClass>
到左值MyClass
的转换。然而,Boost。Python目前不支持自定义左值转换。因此,会抛出一个ArgumentError
异常。
使用def_readonly("spam", &Factory::spam)
公开成员变量时,相当于通过公开
add_property("spam", make_getter(&Factory::spam, return_internal_reference()))
助推。当以这种方式公开的类型是boost::shared_ptr
时,Python有特殊的代码。由于它是只读属性,并且std::shared_ptr
是要复制的,因此使用类型为return_by_value
的返回值策略公开std::shared_ptr
的副本是安全的。
这里是一个完整的例子,其中Factory
公开由std::shared_ptr
保持的Spam
对象和由boost::shared_ptr
保持的Egg
对象:
#include <iostream>
#include <memory> // std::shared_ptr, std::make_shared
#include <string>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/python.hpp>
/// @brief Mockup Spam type.
struct Spam
{
~Spam() { std::cout << "~Spam()" << std::endl; }
void someFunc(std::string str)
{
std::cout << "Spam::someFunc() " << this << " : " << str << std::endl;
}
};
/// @brief Mockup Egg type.
struct Egg
{
~Egg() { std::cout << "~Egg()" << std::endl; }
void someFunc(std::string str)
{
std::cout << "Egg::someFunc() " << this << " : " << str << std::endl;
}
};
/// @brief Mockup Factory type.
struct Factory
{
Factory()
: spam(std::make_shared<Spam>()),
egg(boost::make_shared<Egg>())
{
spam->someFunc("factory");
egg->someFunc("factory");
}
std::shared_ptr<Spam> spam;
boost::shared_ptr<Egg> egg;
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose Factory class and its member variables.
python::class_<Factory>("Factory")
// std::shared_ptr<Spam>
.add_property("spam", python::make_getter(&Factory::spam,
python::return_value_policy<python::return_by_value>()))
// boost::shared_ptr<Egg>
.def_readonly("egg", &Factory::egg)
;
// Expose Spam as being held by std::shared_ptr.
python::class_<Spam, std::shared_ptr<Spam>>("Spam")
.def("someFunc", &Spam::someFunc)
;
// Expose Egg as being held by boost::shared_ptr.
python::class_<Egg, boost::shared_ptr<Egg>>("Egg")
.def("someFunc", &Egg::someFunc)
;
}
交互式Python演示用法和对象生存期:
>>> import example
>>> factory = example.Factory()
Spam::someFunc() 0x8d73250 : factory
Egg::someFunc() 0x8d5dbc9 : factory
>>> factory.spam.someFunc("python")
Spam::someFunc() 0x8d73250 : python
>>> factory.egg.someFunc("python")
Egg::someFunc() 0x8d5dbc9 : python
>>> factory = None
~Egg()
~Spam()
>>> factory = example.Factory()
Spam::someFunc() 0x8d73250 : factory
Egg::someFunc() 0x8d06569 : factory
>>> spam = factory.spam
>>> factory = None
~Egg()
>>> spam.someFunc("python")
Spam::someFunc() 0x8d73250 : python
>>> spam = None
~Spam()
>>> factory = example.Factory()
Spam::someFunc() 0x8d73250 : factory
Egg::someFunc() 0x8ce10f9 : factory
>>> egg = factory.egg
>>> factory = None
~Spam()
>>> egg.someFunc("python")
Egg::someFunc() 0x8ce10f9 : python
>>> egg = None
~Egg()
还没有测试过,但这可能有效:
boost::python::register_ptr_to_python<std::shared_ptr<MyClass>>();
来源:http://www.boost.org/doc/libs/1_55_0/libs/python/doc/v2/register_ptr_to_python.html
- Qt SQLite没有查询或参数计数不匹配
- 模板参数推导失败,函数参数/参数不匹配
- 在使用累加时,C++中的运算符+不匹配
- C++ 与操作员不匹配<<
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- 与'operator='不匹配(操作数类型'String'且"void")
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- C4018:类内有符号、无符号不匹配
- 我在 .h 中有一个枚举类,并且在.cpp错误中有一个运算符重载:与"运算符<<不匹配
- 为什么我收到错误:"运算符<<不匹配?
- RE2 不匹配非 ASCII 字符
- 函数签名与调用的函数不匹配,常量字符[]和字符*之间的区别?
- 模板推导:为什么函数指针模板定义在常量和/或引用时不匹配?
- 错误:"模板<类_Tp,类_Dp>类 std::unique_ptr"的模板参数列表中参数 1 的类型/值不匹配
- OpenSSL fips in C++ wrapper Library 如何?错误:指纹不匹配
- 为什么我的数组值与此处的全局变量不匹配?
- 引号之间匹配/不匹配,带有不可避免的引号和多行
- 映射迭代器与运算符不匹配
- C++调用和定义不匹配
- 模板专用化与派生类不匹配