- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这是一个我无法使用文档回答的 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_converter,因为 A 已经使用 class_<> 导出?这将彻底解决我的问题(尽管我愿意接受其他建议)。
谢谢!K
最佳答案
一个类型只需要注册一个到 Python 的转换。
当类通过 boost::python::class_
公开时, 类型信息和注册发生。此外,如果未提供 boost::noncopyable
,则会注册将按值复制 T
的到 Python 和从 Python 的转换器。用户可以使用 boost::python::to_python_converter
注册自己的自定义转换器.
因此,一种解决方案是使用 boost::noncopyable
抑制类 A
的默认转换器,然后注册一个自定义转换器,该转换器将创建包含任一实例的 Python 对象A
或 B
的实例。这种方法将在 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.
}
};
这是一个完整的例子demonstrating这种方法:
#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))
关于c++ - 为使用 class_<> 导出的类绕过 to_python 注册表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17824901/
这是一个我无法使用文档回答的 boost.python 问题。 我有两个 C++ 类 A 和 B,这样 B 是 A 的子类,在某些条件下,类型 A 的对象可以转换为类型 B 的对象。这两个类都使用 c
我已经用 C++ 编写了一个类的一部分,我希望能够将它与 Python GUI 结合使用,所以我使用 Boost.Python 来尝试让它变得简单。我遇到的问题是,按照他们的指南 ( http://w
我无法获取绿色数据( yo = requests.get('http://www.nfl.com/schedules/2019/REG11') soup = bs.BeautifulSoup(yo.t
在我的WPF MVVM项目中,出现此错误: InvalidCastException: Unable to cast object of type 'Mocks.DDD_AutoRadio_Gener
我是一名优秀的程序员,十分优秀!