我在带有 MSVC2010 的 Windows 上使用 Boost.Python 1.54,我在从 python 存储指向第二个类中的一个类的指针并检索它时遇到问题。它似乎以某种方式改变了数据类型。
这是我的课程:
typedef unsigned int uint_t;
struct classA {
int intval;
unsigned int bitfield_member:1;
};
struct Collection {
classA * class_a_ptr;
};
以下是我将它们暴露给 python 的方式(其中一些代码最初是由 Py++ 自动生成的,但从那时起我手动编辑了它):
#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) );
}
}
这是运行它的python测试:
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})
这对我来说似乎很奇怪,因为 classA_wrapper 扩展了 classA。我究竟做错了什么?有不同的方法可以做到这一点吗?我在 python 和 c++ 方面非常有经验,但这是我第一次尝试 Boost.Python。