我已将代码简化为以下可编译代码,其中包含 gcc13、boost 1.78 和 python3。
#include <iostream>
#include <string>
#include <boost/python.hpp>
template <typename base, typename derived>
class cloneable : public base
{
protected:
using base::base;
virtual base* clone() const override
{
return new derived{static_cast<derived const &>(*this)};
}
};
struct SX {};
struct MT {
virtual const std::string& type() const =0;
virtual const SX* xc() const =0;
virtual MT* clone() const =0;
virtual ~MT() = default;
};
struct F3MT : public cloneable<MT,F3MT> {
const MT* underlying_ = nullptr;
static inline const std::string t{"F"};
const std::string& type() const override { return t; }
const SX* xc() const override { return nullptr; }
};
using namespace boost::python;
template <typename cppclass_t>
struct cppclass_ptr_to_python_obj
{
static PyObject* convert(const cppclass_t* mptr)
{
if (!mptr)
Py_RETURN_NONE;
return incref( object(mptr).ptr() );
}
};
MT* get_fm()
{
auto* fm = new F3MT;
auto* fmu = new F3MT;
fm->underlying_ = fmu;
return fm;
}
BOOST_PYTHON_MODULE(myseven)
{
class_<MT, MT*, boost::noncopyable>("MT", no_init)
.def("type", &MT::type, return_value_policy<copy_const_reference>{} )
.def("xc", &MT::xc,
return_value_policy<reference_existing_object>{})
;
to_python_converter<const MT*, cppclass_ptr_to_python_obj<MT>>{};
class_<F3MT, F3MT*, bases<MT>>("F3MT")
.def_readonly("underlying", &F3MT::underlying_)
;
to_python_converter<const F3MT*, cppclass_ptr_to_python_obj<F3MT>>{};
def("getfm", &get_fm, return_value_policy<reference_existing_object>{});
}
我构建了一个.so并将其加载到python中,得到以下错误。 我正在尝试通过指针传递 MT。
>>import myseven.so
>>x = myseven.getfm()
>>x.underlying
TypeError: No to_python (by-value) converter found for C++ type: MT
我认为通过注册转换来作用于指针,就不需要按值转换。毕竟我将指针存储为成员。
请忽略内存泄漏,因为这是简化的代码。
cppclass_ptr_to_python_obj 转换器需要托管一个转换函数,该函数在 const-ptr 之上也接受 cppclass_t 的 const-ref。