python之boost python make_constructor 和 custodians 和 ward
落叶无声
阅读:34
2025-04-02 23:11:03
评论:0
假设我有以下两个 C++ 类(我无法修改):
struct A
{
// stuff
};
struct B
{
// B will internally hold a reference to a
B(A& a, some_cpp_only_type arg);
};
我正在尝试包装 B 类并隐藏
some_cpp_only_type
来自 Python 接口(interface)的参数(没有此参数的
B
没有替代构造函数)。
我现在有以下包装代码:
using namespace boost::python;
boost::shared_ptr<B> make_B(A& a)
{
return boost::make_shared<B>(a, get_cpp_only_instance());
}
BOOST_PYTHON_MODULE(my_module)
{
class_<B, boost::noncopyable>("B", no_init)
.def("__init__", make_constructor(&make_B));
}
现在这有效,因为我持有对已包装
A
的引用Python内部的对象。但是,我真的很想至少在
B
的实例之前保留它。被摧毁。我尝试添加
with_custodian_and_ward_postcall
调用政策至
make_constructor
,但我得到几页无意义的编译器错误(甚至来自 Clang)。这是修改后的无效代码:
using namespace boost::python;
boost::shared_ptr<B> make_B(A& a)
{
return boost::make_shared<B>(a, get_cpp_only_instance());
}
BOOST_PYTHON_MODULE(my_module)
{
class_<B, boost::noncopyable>("B", no_init)
.def("__init__", make_constructor(&make_B, with_custodian_and_ward_postcall<0,1>()));
}
使用
make_constructor
时如何正确指定调用策略?
使用 make_function 的替代尝试
我尝试使用解决方案 Tanner Sansbury posted here用
make_function
包装相反,但这一次即使编译成功,我也会得到
ValueError
从 Python 内部:
No to_python (by-value) converter found for C++ type: A
作为引用,这是我尝试使用的代码
make_function
(无论有没有保管人/病房调用政策,我都会遇到同样的错误):
using namespace boost::python;
boost::shared_ptr<B> make_B(A& a)
{
return boost::make_shared<B>(a, get_cpp_only_instance());
}
void inter_make_B(object self, A& a)
{
auto constructor = make_constructor(&make_B);
constructor(self, a);
}
BOOST_PYTHON_MODULE(my_module)
{
class_<B, boost::noncopyable>("B", no_init)
.def("__init__", make_function(&inter_make_B, with_custodian_and_ward<1,2>()));
}
如何正确编写
B
的包装器无需修改
B
即可正确管理内存类(class)?
请您参考如下方法:
我知道这篇文章已经有 3 年历史了,但我自己一直在寻找这个并且无法找到任何开箱即用的解决方案,只需对原始代码进行最少的修改。多亏了this other post,我终于设法让它工作了.
这是基于您提供的代码段的模拟:
using namespace boost::python;
boost::shared_ptr<B> make_B(A& a)
{
return boost::make_shared<B>(a, get_cpp_only_instance());
}
void make_B_wrapper(object self, A& a)
{
auto constructor = make_constructor(&make_B);
constructor(self, a);
}
BOOST_PYTHON_MODULE(my_module)
{
class_<B, boost::noncopyable>("B", no_init)
.def("__init__", &make_B_wrapper, with_custodian_and_ward_postcall<1,2>());
}
这是一个完整的工作 example演示这种方法:
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
namespace python = boost::python;
/// @brief Mockup class with verbose construction and destruction.
class Foo
{
public:
Foo() { std::cout << "Foo() " << this << std::endl; }
~Foo() { std::cout << "~Foo() " << this << std::endl; }
};
/// @brief Mockup class with verbose construction and destruction.
class Bar
{
public:
Bar() { std::cout << "Bar() " << this << std::endl; }
~Bar() { std::cout << "~Bar() " << this << std::endl; }
};
/// @brief Mockup factory function.
boost::shared_ptr<Foo> makeFoo(std::shared_ptr<Bar> & /* unused */)
{
return boost::make_shared<Foo>();
}
static void makeFooWrapper(python::object & self, std::shared_ptr<Bar> & bar)
{
auto constructor = python::make_constructor(&makeFoo);
constructor(self, bar);
}
BOOST_PYTHON_MODULE(example)
{
python::class_<Bar, std::shared_ptr<Bar>, boost::noncopyable>("Bar", python::init<>());
python::class_<Foo, std::shared_ptr<Foo>, boost::noncopyable>("Foo", python::no_init)
.def("__init__", &makeFooWrapper,
python::with_custodian_and_ward_postcall<1, 2>());
}
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。