I have simplified my code to the following compilable code, with gcc13, boost 1.78 and 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>{});
}
I build a .so and load it into python, get the following error. I'm trying to pass MT around by pointer.
>>import myseven.so
>>x = myseven.getfm()
>>x.underlying
TypeError: No to_python (by-value) converter found for C++ type: MT
I thought that by registering the converted to act on pointers, the by-value converted is not required. I am storing a pointer as a member after all.
Please ignore memory leaks as this is a simplifed code.
The cppclass_ptr_to_python_obj convertor needs to host a convert function that takes a const-ref to cppclass_t as well, on top of the const-ptr.