to_python_converter , is by value needed?

78 Views Asked by At

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.

1

There are 1 best solutions below

0
MMM On

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.