为什么 python-exposed boost::gregorian::date 不是随处可用?
Why isn't python-exposed boost::gregorian::date available everywhere?
我用以下内容公开了 boost::gregorian::date:
date_from_python_date{};
to_python_converter<date, date_to_python_date, true>{};
其中 date_to_python_date 是具有正确转换函数的结构:它将其转换为 python datetime.date。
一些 c++ 函数 return 日期并从 python 调用它们有效。
后期有c++的class
class F {
/// ....
public:
boost::gregorian::date start;
};
我注册的是:
class_<F, F*, bases<B>>("F")
.def_readwrite("start", &F::start, "FTD")
;
我在 python 注册日期后执行此操作。
然后,我获得了 F 包装器的一个实例 f。但是,当我打印
f.start
错误是:
No Python class registered for C++ class boost::gregorian::date
简而言之,def_readonly()
和def_readwrite()
使用的return策略将默认使用return_internal_reference
for user-defined class types (see make_getter()
). This return policy will suppress the use of custom converters. To resolve this, replace def_readonly()
and def_readwrite()
with add_property()
, providing a boost::python::return_value_policy
with a type of boost::python::return_by_value
。
变化:
namespace python = boost::python;
python::class_<F, F*, python::bases<B>>("F")
.def_readwrite("start", &F::start, "FTD")
;
至:
namespace python = boost::python;
python::class_<F, F*, python::bases<B>>("F")
.add_property("start",
python::make_getter(
&F::start, python::return_value_policy<python::return_by_value>()),
python::make_setter(
&F::start, python::return_value_policy<python::return_by_value>()),
"FTD")
;
这里有一个完整的例子demonstrating这个区别:
#include <boost/python.hpp>
/// Mocks...
// Mockup user defined type.
class spam {};
struct egg
{
spam spam;
};
// Mockup convert that converts spam into 'hello world' strings.
struct spam_converter
{
static PyObject* convert(const spam&)
{
namespace python = boost::python;
python::str result("hello world");
return python::incref(result.ptr());
}
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Enable spam to string converter.
python::to_python_converter<spam, spam_converter>();
// Expose egg.
python::class_<egg>("Egg")
// Expose egg::spam as spam1, access will fail to find converter.
.def_readonly("spam1", &egg::spam)
// Expose egg::spam as spam2, automatic conveter will be found.
.add_property("spam2",
python::make_getter(
&egg::spam, python::return_value_policy<python::return_by_value>()))
;
}
交互使用:
>>> import example
>>> egg = example.Egg()
>>> try:
... spam = egg.spam1 # expect to throw
... assert(False)
... except TypeError:
... assert(True)
...
>>> spam = egg.spam2
>>> assert(spam == "hello world")
请注意,虽然相同的 egg::spam
数据成员实例被公开为 Egg.spam1
和 Egg.spam2
,但公开数据成员的方式会影响是否发货时发现自动转换器
我用以下内容公开了 boost::gregorian::date:
date_from_python_date{};
to_python_converter<date, date_to_python_date, true>{};
其中 date_to_python_date 是具有正确转换函数的结构:它将其转换为 python datetime.date。 一些 c++ 函数 return 日期并从 python 调用它们有效。
后期有c++的class
class F {
/// ....
public:
boost::gregorian::date start;
};
我注册的是:
class_<F, F*, bases<B>>("F")
.def_readwrite("start", &F::start, "FTD")
;
我在 python 注册日期后执行此操作。 然后,我获得了 F 包装器的一个实例 f。但是,当我打印
f.start
错误是:
No Python class registered for C++ class boost::gregorian::date
简而言之,def_readonly()
和def_readwrite()
使用的return策略将默认使用return_internal_reference
for user-defined class types (see make_getter()
). This return policy will suppress the use of custom converters. To resolve this, replace def_readonly()
and def_readwrite()
with add_property()
, providing a boost::python::return_value_policy
with a type of boost::python::return_by_value
。
变化:
namespace python = boost::python;
python::class_<F, F*, python::bases<B>>("F")
.def_readwrite("start", &F::start, "FTD")
;
至:
namespace python = boost::python;
python::class_<F, F*, python::bases<B>>("F")
.add_property("start",
python::make_getter(
&F::start, python::return_value_policy<python::return_by_value>()),
python::make_setter(
&F::start, python::return_value_policy<python::return_by_value>()),
"FTD")
;
这里有一个完整的例子demonstrating这个区别:
#include <boost/python.hpp>
/// Mocks...
// Mockup user defined type.
class spam {};
struct egg
{
spam spam;
};
// Mockup convert that converts spam into 'hello world' strings.
struct spam_converter
{
static PyObject* convert(const spam&)
{
namespace python = boost::python;
python::str result("hello world");
return python::incref(result.ptr());
}
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Enable spam to string converter.
python::to_python_converter<spam, spam_converter>();
// Expose egg.
python::class_<egg>("Egg")
// Expose egg::spam as spam1, access will fail to find converter.
.def_readonly("spam1", &egg::spam)
// Expose egg::spam as spam2, automatic conveter will be found.
.add_property("spam2",
python::make_getter(
&egg::spam, python::return_value_policy<python::return_by_value>()))
;
}
交互使用:
>>> import example
>>> egg = example.Egg()
>>> try:
... spam = egg.spam1 # expect to throw
... assert(False)
... except TypeError:
... assert(True)
...
>>> spam = egg.spam2
>>> assert(spam == "hello world")
请注意,虽然相同的 egg::spam
数据成员实例被公开为 Egg.spam1
和 Egg.spam2
,但公开数据成员的方式会影响是否发货时发现自动转换器