Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ArgumentError在Boost中的类中存储和检索指针时出错。Python:类型错误_C++_Python_Boost Python - Fatal编程技术网

C++ ArgumentError在Boost中的类中存储和检索指针时出错。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; }; 下面是我如何

我在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;
};
下面是我如何将它们公开给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_包装器::集合_位字段_成员)
;
}
}
<> >虽然 GETH-BITFIELLION成员和 StIdBiFieldSeaEng/Sudio>是原始代码中的成员函数,但从 CyraseAypTr> /Cudio>返回的Python < Cord> CaseA< /Cord>对象似乎没有完全初始化它的基础C++类型。这可能是Boost.pythonapi中未定义行为的结果

问题不会在其他地方出现,因为:

  • Collection.class_a_ptr
    属性的fget和fset显式接受实例参数
  • classA.intval
    属性使用
    def_readwrite
    ,这将隐式创建通过接受实例的fget和fset

以下是基于原始代码的完整示例:

#包括
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_包装器::集合_位字段_成员)
;
}
}
<> >虽然 GETH-BITFIELLION成员和 StIdBiFieldSeaEng/Sudio>是原始代码中的成员函数,但从 CyraseAypTr> /Cudio>返回的Python < Cord> CaseA< /Cord>对象似乎没有完全初始化它的基础C++类型。这可能是Boost.pythonapi中未定义行为的结果

问题不会在其他地方出现,因为:

  • Collection.class_a_ptr
    属性的fget和fset显式接受实例参数
  • classA.intval
    pro
    #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})