绕过to_python class_<>导出类的注册表?
bypassing to_python registry for class exported with class_<>?
这里有一个boost.python问题,我无法使用文档回答。
我有两个C++类A和B,这样B是A的子类,在某些条件下,类型A的对象可以转换为类型B的对象。这两个类都是用class_<>导出的。示意图:
class A
{
public:
bool is_B() const { ... } // returns true if conversion to B will succeed
...
};
class B : public A {
B(const A &a) { ... } // should only be called if a.is_B() == true
...
};
class_<A>("A") ... ;
class_<B,bases<A> >("B") ... ;
如果可能的话,我希望类A的到python转换器返回类B的对象;否则它应该返回一个类A的对象。模式:
struct A_to_python_converter {
PyObject *convert(const A &a) {
if (a.is_B())
// return object of class B
return boost::python::incref(boost::python::object(B(a)).ptr());
else
... // return object of class A
}
}
boost::python::to_python_converter<A,A_to_python_converter>();
问题是,我不确定用什么代码来代替上面的"…"。如果我放:
// return object of class A
return boost::python::incref(boost::python::object(a).ptr());
那么我得到了一个无限循环,因为A_to_python_converter::convert()将被递归调用。有没有一种方法可以绕过注册表,将类a的对象转换为(PyObject*),而不需要经过a_to_python_controller,因为a已经用class_<>导出?这将彻底解决我的问题(尽管我对其他建议持开放态度)。
谢谢!K
一个类型只需要注册一个到Python的转换。
当类通过boost::python::class_
公开时,会发生类型信息和注册。此外,如果未提供boost::noncopyable
,则注册到Python和从Python将按值复制T
的转换器。用户可以使用boost::python::to_python_converter
注册自己的自定义转换器。
因此,一种解决方案是使用boost::noncopyable
抑制类A
的默认转换器,然后注册一个自定义转换器,该转换器将创建包含A
实例或B
实例的Python对象。这种方法将在Boost.Python中使用较低级别的API来处理实例创建。
/// @brief Custom converter that converts A to either an A or B Python object.
struct class_A_cref_wrapper
: boost::python::to_python_converter<A, class_A_cref_wrapper>
{
// Type that makes instances that hold A by value.
typedef boost::python::objects::make_instance<A,
boost::python::objects::value_holder<A>
> instance_maker;
static PyObject* convert(const A& a)
{
namespace python = boost::python;
return a.is_B()
? python::incref(python::object(B(a)).ptr()) // Create B.
: instance_maker::execute(boost::ref(a)); // Create A.
}
};
下面是一个完整的例子来演示这种方法:
#include <boost/python.hpp>
// Legacy API.
class A
{
public:
A() : b_(false) {}
A(bool b) : b_(b) {}
bool is_B() const { return b_; } // true if conversion to B will succeed
private:
bool b_;
};
class B: public A
{
public:
B() : A() {}
B(const A& a) : A(a) {}
};
/// @brief Factory functions that return an A type with is_B of false.
A make_A() { return A(false); }
/// @brief Factory functions that return an A type with is_B of true.
A make_B() { return A(true); }
/// @brief Custom converter that converts A to either an A or B Python object.
struct class_A_cref_wrapper
: boost::python::to_python_converter<A, class_A_cref_wrapper>
{
// Make and hold instances by value.
typedef boost::python::objects::make_instance<A,
boost::python::objects::value_holder<A>
> instance_maker;
static PyObject* convert(const A& a)
{
namespace python = boost::python;
return a.is_B()
? python::incref(python::object(B(a)).ptr()) // Create B.
: instance_maker::execute(boost::ref(a)); // Create A.
}
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose A and B classes. Use boost::noncopyable to suppress to-Python
// and from-Python converter regristration for class A.
python::class_<A, boost::noncopyable>("A");
python::class_<B, python::bases<A> >("B");
// Register a custom converter for A.
class_A_cref_wrapper();
// Expose factory functions that always return an A type. This will
// cause to_python converters to be invoked when invoked from Python.
python::def("make_A", &make_A);
python::def("make_B", &make_B);
}
交互式使用:
>>> import example
>>> assert(isinstance(example.make_A(), example.A))
>>> assert(isinstance(example.make_B(), example.B))
>>> assert(isinstance(example.make_B(), example.A))
>>> assert(not isinstance(example.make_A(), example.B))
相关文章:
- 有没有任务栏API可以立即应用注册表更改
- 检查注册表项是否链接到(或副本)另一个注册表项
- 禁用地址共享注册表不起作用
- 如何从注册表项中提取配置单元和注册表名称
- 注册表正在设置 1 个字符
- 清理"QSettings"注册表项的最佳方法(Windows上的Qt 5)
- 在 c++ 中编辑注册表项
- 某些进程的注册表限制
- 在编译时生成某种子类/类型注册表?
- 如何测试注册表项是否存在?
- 注册表-获取值(而不是键)上次更改的时间和键创建日期
- 从注册表中检索已注销用户的 sid
- 如何正确检查 c++ 是否存在注册表项?
- 如何在不使用任何数据库的情况下制作动态注册表单?
- 强制资源管理器重新加载注册表值
- 以编程方式锁定注册表项以避免并发问题
- 如何应用注册表模式使"select class depend on input"遵守开放封闭原则?
- 如何恢复注册表项的有效权限?C++
- 如何防止 C API 注册表中的 Lua 回调被垃圾回收?
- 如何修改QT中的注册表设置