C++ ArgumentError在Boost中的类中存储和检索指针时出错。Python:类型错误
我在Windows和MSVC2010上使用Boost.Python1.54,在从Python存储指向第二个类中的一个类的指针并检索它时遇到问题。它似乎在某种程度上改变了数据类型 以下是我的课程:C++ ArgumentError在Boost中的类中存储和检索指针时出错。Python:类型错误,c++,python,boost-python,C++,Python,Boost Python,我在Windows和MSVC2010上使用Boost.Python1.54,在从Python存储指向第二个类中的一个类的指针并检索它时遇到问题。它似乎在某种程度上改变了数据类型 以下是我的课程: typedef unsigned int uint_t; struct classA { int intval; unsigned int bitfield_member:1; }; struct Collection { classA * class_a_ptr; }; 下面是我如何
typedef unsigned int uint_t;
struct classA {
int intval;
unsigned int bitfield_member:1;
};
struct Collection {
classA * class_a_ptr;
};
下面是我如何将它们公开给python的(其中一些代码最初是由Py++自动生成的,但从那时起我一直手工编辑):
在第一个“fails”行出现此错误时失败:
这对我来说似乎很奇怪,因为classA_包装器扩展了classA。我做错了什么?有没有其他方法可以做到这一点?我在Python和C++方面很有经验,但这是我第一次进入Booost。python。 < P>在代码< > BistFieldMys< /Cuff>属性> <代码> CaseA< /Cord>中,需要显式接受它们操作的实例。它相当于Python中的方法,其中fget和fset接受
self
参数。因此,将bitfield\u成员
getter和setter函数更改为静态,并接受classA&
作为它们的第一个参数
/。。。
结构类A_包装:。。。
{
// ...
静态::uint\u t get\u位字段成员(classA和self)
{
返回self.bitfield_成员;
}
静态无效集\位字段\成员(classA&self,::uint\t new\u值)
{
self.bitfield_member=新的_值;
}
};
BOOST_PYTHON_模块(…)
{
名称空间python=boost::python;
// ...
python::class(类包装器)(“类A”)
.def_readwrite(“intval”和classA::intval)
.add_属性(“位字段_成员”,
&classA\u包装器::获取\u位字段\u成员,
&classA_包装器::集合_位字段_成员)
;
}
}
<> >虽然
属性的fget和fset显式接受实例参数Collection.class_a_ptr
属性使用classA.intval
,这将隐式创建通过接受实例的fget和fsetdef_readwrite
以下是基于原始代码的完整示例:
#包括
typedef无符号整数单位;
结构类A
{
int intval;
无符号整数位域\成员:1;
};
结构集合
{
a类*a类ptr;
};
名称空间python=boost::python;
结构集合包装器
:集合,python::包装器
{
集合_包装器(){}
集合包装器(常量集合和自身)
:收集(自我)
{}
静态::classA*get_class_a_ptr(常量集合和自身)
{
返回self.class_a_ptr;
}
静态无效集\u类\u a\u ptr(集合和自身,::类a*新值)
{
self.class_a_ptr=新的_值;
}
};
结构类A_包装器
:classA,python::wrapper
{
类A_包装器(){}
classA_包装器(const classA&self)
:classA(自我)
{}
静态::uint\u t get\u位字段成员(const classA和self)
{
返回self.bitfield_成员;
}
静态无效集\位字段\成员(classA&self,::uint\t new\u值)
{
self.bitfield_member=新的_值;
}
};
BOOST_PYTHON_模块(示例)
{
python::类(集合)
.add_属性(“class_a_ptr”,
python::make_函数(&Collection_wrapper::get_class_a_ptr),
python::return_internal_reference()),
python::make_函数(&Collection_wrapper::set_class_a_ptr),
python::with_保管人_和_病房_后置调用())
;
python::类(classA)
.def_readwrite(“intval”和classA::intval)
.add_属性(“位字段_成员”,
&classA\u包装器::获取\u位字段\u成员,
&classA_包装器::集合_位字段_成员)
;
}
及其用法:
>>导入示例
>>>collection=example.collection()
>>>a=示例.classA()
>>>a.intval=9801
>>>打印a.intval
9801
>>>collection.class_a_ptr=a
>>>相同的\u a=collection.class\u a\u ptr
>>>a.bitfield_成员=0
>>>打印a.bitfield\u成员
0
>>>打印相同的\u位字段\u成员
0
>>>相同的\u a.位字段\u成员=1
>>>打印a.bitfield\u成员
1.
>>>打印相同的\u位字段\u成员
1.
暴露于classA
上的位域成员
属性的函子需要显式接受其操作的实例。它相当于Python中的方法,其中fget和fset接受self
参数。因此,将bitfield\u成员
getter和setter函数更改为静态,并接受classA&
作为它们的第一个参数
/。。。
结构类A_包装:。。。
{
// ...
静态::uint\u t get\u位字段成员(classA和self)
{
返回self.bitfield_成员;
}
静态无效集\位字段\成员(classA&self,::uint\t new\u值)
{
self.bitfield_member=新的_值;
}
};
BOOST_PYTHON_模块(…)
{
名称空间python=boost::python;
// ...
python::class(类包装器)(“类A”)
.def_readwrite(“intval”和classA::intval)
.add_属性(“位字段_成员”,
&classA\u包装器::获取\u位字段\u成员,
&classA_包装器::集合_位字段_成员)
;
}
}
<> >虽然
属性的fget和fset显式接受实例参数Collection.class_a_ptr
proclassA.intval
#include <boost/python.hpp> #include <boost/python/module.hpp> #include <boost/python/def.hpp> #include <boost/python/return_value_policy.hpp> #include <boost/python/manage_new_object.hpp> namespace bp = boost::python; struct Collection_wrapper : Collection, bp::wrapper< Collection > { Collection_wrapper(Collection const & arg ) : Collection( arg ) , bp::wrapper< Collection >(){ // copy constructor } Collection_wrapper() : Collection() , bp::wrapper< Collection >(){ // null constructor } static ::classA * get_class_a_ptr(Collection const & inst ){ return inst.class_a_ptr; } static void set_class_a_ptr( Collection & inst, ::classA * new_value ){ inst.class_a_ptr = new_value; } }; struct classA_wrapper : classA, bp::wrapper< classA > { classA_wrapper(classA const & arg ) : classA( arg ) , bp::wrapper< classA >(){ // copy constructor } classA_wrapper() : classA() , bp::wrapper< classA >(){ // null constructor } ::uint_t get_bitfield_member() const { return bitfield_member; } void set_bitfield_member( ::uint_t new_value ){ bitfield_member = new_value; } }; BOOST_PYTHON_MODULE(render_lib_ext) { using namespace bp; { //::Collection typedef bp::class_< Collection_wrapper > Collection_exposer_t; Collection_exposer_t Collection_exposer = Collection_exposer_t( "Collection" ); bp::scope Collection_scope( Collection_exposer ); // original version, fails Collection_exposer.add_property( "class_a_ptr" , bp::make_function( (::classA * (*)( ::Collection const & ))(&Collection_wrapper::get_class_a_ptr), bp::return_internal_reference< >() ) , bp::make_function( (void (*)( ::Collection &,::classA * ))(&Collection_wrapper::set_class_a_ptr), bp::with_custodian_and_ward_postcall< 1, 2 >() ) ); } { //::classA typedef bp::class_< classA_wrapper > classA_exposer_t; classA_exposer_t classA_exposer = classA_exposer_t( "classA" ); bp::scope classA_scope( classA_exposer ); classA_exposer.def_readwrite( "intval", &classA::intval ); classA_exposer.add_property( "bitfield_member" , (::uint_t ( classA_wrapper::* )( ) const)(&classA_wrapper::get_bitfield_member) , (void ( classA_wrapper::* )( ::uint_t ) )(&classA_wrapper::set_bitfield_member) ); } }
import unittest import render_lib_ext as RL class TestRenderLib(unittest.TestCase): def test_globals(self): coll=RL.Collection() g = RL.classA() g.intval=9801; self.assertEqual(9801, g.intval) coll.class_a_ptr = g # store pointer in collection geg = coll.class_a_ptr # retrieve it self.assertEqual(0, g.bitfield_member) # works self.assertEqual(0, geg.bitfield_member) # fails with ArgumentError (type error) self.assertEqual(9801, geg.intval) # fails! Is it not the same object?
Traceback (most recent call last): File "test2.py", line 18, in test_globals self.assertEqual(0, geg.bitfield_member) # fails with ArgumentError (type error) ArgumentError: Python argument types in None.None(classA) did not match C++ signature: None(struct classA_wrapper {lvalue})