我有以下(简化)代码:
struct A
{
int intVal;
char charVal;
};
struct B
{
A* someObj;
};
我想公开B::A::intVal
,但以下剂量不起作用:
class_<B>("someClass")
.def_readonly("var", &B::A::intVar)
;
我该怎么做?
答案 0 :(得分:2)
我假设你以某种方式填充B::someObj
,或者访问可能随机的指针会导致代码崩溃。鉴于这种情况,您必须公开A和B以访问A到B.我测试了以下代码,它编译并按预期工作:
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
struct A
{
int intVal;
char charVal;
};
struct B
{
A* someObj;
};
static boost::shared_ptr<B> create_b() {
boost::shared_ptr<B> retval(new B);
retval->someObj = new A; //<< WARNING: leakage ahead
retval->someObj->intVal = 3;
retval->someObj->charVal = 'a';
return retval;
}
BOOST_PYTHON_MODULE(test)
{
using namespace boost::python;
class_<A, A* >("A")
.def_readonly("intVal", &A::intVal)
.def_readonly("charVal", &A::charVal)
;
class_<B, boost::shared_ptr<B> >("B")
.def("__init__", make_constructor(&create_b))
.def_readonly("someObj", &B::someObj)
;
}
我的个人提示:如果您可以访问B
的定义,请将访问指针从B更改为A以使用boost::shared_ptr<A>
。 Boost.Python可以正常处理优雅和引用计数。在这种情况下,您的代码将会是这样的:
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
struct A
{
int intVal;
char charVal;
};
struct B
{
boost::shared_ptr<A> someObj;
};
static boost::shared_ptr<B> create_b() {
boost::shared_ptr<B> retval(new B);
retval->someObj.reset(new A); //< no more leaks
retval->someObj->intVal = 3;
retval->someObj->charVal = 'a';
return retval;
}
BOOST_PYTHON_MODULE(test)
{
using namespace boost::python;
class_<A, boost::shared_ptr<A> >("A")
.def_readonly("intVal", &A::intVal)
.def_readonly("charVal", &A::charVal)
;
class_<B, boost::shared_ptr<B> >("B")
.def("__init__", make_constructor(&create_b))
.def_readonly("someObj", &B::someObj)
;
}
在linux下,你可以像这样编译和测试这个模块:
$ g++ -I/usr/include/python2.7 -shared -fpic test.cc -lboost_python -lpython2.7 -o test.so
运行Python并检查代码是否有效:
>>> import test
>>> b = test.B()
>>> b.someObj.intVal
3
>>> b.someObj.charVal
'a'
答案 1 :(得分:2)
B::A::intVar
不起作用,因为它是一个格式错误的合格ID。我选择将问题分成两部分:qualified-id和暴露Boost.Python中成员的成员。
以下代码将两个结构体引入同一名称空间。因此,B::A
的限定ID不存在,因为B
不会将A
重新引入为嵌套标识符:
struct A
{
int intVal;
char charVal;
};
struct B
{
A* someObj;
};
要在A
中引入B
标识符,B
要么需要:
包含A
结构的定义。 (即A
成为嵌套结构。)
struct B
{
struct A // introduces B::A
{
int intVal;
char charVal;
};
A* someObj;
};
为A
提供typedef。
struct A
{
int intVal;
char charVal;
};
struct B
{
typedef ::A A; // introduces B::A
A* someObj;
};
要直接公开成员的成员,Boost.Python将需要一个简单的帮助函数,例如:
/// @brief Helper function that returns B.someObj.intVal.
int get_b_intval(const B& self)
{
return self.someObj->intVal;
}
辅助函数可以作为Python B::var
只读属性公开。
namespace python = boost::python;
python::class_<B>("someClass")
.add_property("var", &get_b_intval)
;
这是一个完整的例子:
#include <boost/python.hpp>
struct A
{
int intVal;
char charVal;
};
struct B
{
A* someObj;
};
/// @brief Helper function that returns B.someObj.intVal.
int get_b_intval(const B& self)
{
return self.someObj->intVal;
}
/// @brief Helper function to create a B object.
B make_B()
{
static A a;
a.intVal = 42;
B b;
b.someObj = &a;
return b;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<B>("someClass")
.add_property("var", &get_b_intval)
;
python::def("make_B", &make_B);
}
及其用法:
>>> import example
>>> b = example.make_B()
>>> print b.var
42
>>> b.var = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute