[C++-sig] Convert OpenCV class reference return value

Chris Schnaufer chris.schnaufer at eagleview.com
Tue Apr 4 16:58:57 EDT 2017


Thank you for the quick response. I have included the full code (at the bottom of the message) of how I think it "should" work. I've put "should" in quotes because it's based upon my understanding of how to put a converter from C++ to Python together. Compiling this produces two errors (first about no match and second for no get_pytype() declared:

/usr/include/boost/python/detail/invoke.hpp: In instantiation of 'PyObject* boost::python::detail::invoke(boost::python::detail::invoke_tag_<false, true>, const RC&, F&, TC&) [with RC = boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<const Vec3d&>; F = const Vec3d& (UseVec3d::*)() const; TC = boost::python::arg_from_python<UseVec3d&>; PyObject = _object]':
/usr/include/boost/python/detail/caller.hpp:218:46:   required from 'PyObject* boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = const Vec3d& (UseVec3d::*)() const; Policies = boost::python::default_call_policies; Sig = boost::mpl::vector2<const Vec3d&, UseVec3d&>; PyObject = _object]'
/usr/include/boost/python/object/py_function.hpp:38:33:   required from 'PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<const Vec3d& (UseVec3d::*)() const, boost::python::default_call_policies, boost::mpl::vector2<const Vec3d&, UseVec3d&> >; PyObject = _object]'
/root/RAF/RAF/Python/raf.cpp:80:1:   required from here
/usr/include/boost/python/detail/invoke.hpp:88:14: error: no match for call to '(const boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<const Vec3d&>) (const Vec3d&)'
     return rc( (tc().*f)(BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, ac, () BOOST_PP_INTERCEPT)) );

and

/usr/include/boost/python/detail/caller.hpp: In instantiation of 'static const PyTypeObject* boost::python::detail::converter_target_type<ResultConverter>::get_pytype() [with ResultConverter = boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<const Vec3d&>; PyTypeObject = _typeobject]':
/usr/include/boost/python/detail/caller.hpp:240:19:   required from 'static boost::python::detail::py_func_sig_info boost::python::detail::caller_arity<1u>::impl<F, Policies, Sig>::signature() [with F = const Vec3d& (UseVec3d::*)() const; Policies = boost::python::default_call_policies; Sig = boost::mpl::vector2<const Vec3d&, UseVec3d&>]'
/usr/include/boost/python/object/py_function.hpp:48:35:   required from 'boost::python::detail::py_func_sig_info boost::python::objects::caller_py_function_impl<Caller>::signature() const [with Caller = boost::python::detail::caller<const Vec3d& (UseVec3d::*)() const, boost::python::default_call_policies, boost::mpl::vector2<const Vec3d&, UseVec3d&> >]'
/root/RAF/RAF/Python/raf.cpp:80:1:   required from here
/usr/include/boost/python/detail/caller.hpp:102:98: error: 'struct boost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<const Vec3d&>' has no member named 'get_pytype'
         return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype();

> ...
> (But I'm a little confused by your phrasing: Something like
> `class_<cv::Vec3d>` doesn't "redefine" anything, and it doesn't make a
> C++ type "visible" in Python.
> ...
Here I'm trying to understand if I have an OpenCV Vec3d type (that I've defined using p::class_<cv::Vec3d>) getting returned to Python from a function call, how does one prevent collision with the OpenCV Vec3d defined by another library (that uses OpenCV and may be using the same mechanism)? The two declarations may not be compatible despite their apparent similarities (the other library is several revisions behind on OpenCV, for example).

Here is the code with converter. I don't know if there's a preferred way of doing what I'm attempting:

#include <boost/python.hpp>
namespace p = boost::python;

class Vec3d
{
                public:
                  Vec3d() {v[0] = v[1] = v[2] = 0.0;}
                  virtual ~Vec3d() {}
                  double operator[](size_t idx) const {return v[idx];}
                  double& operator[](size_t idx) {return v[idx];}
                private:
                  double v[3];
};

class UseVec3d
{
                public:
                                UseVec3d() {}
                                UseVec3d(const Vec3d& vec) : v(vec) {}
                                virtual ~UseVec3d() {};
                                const Vec3d& get_vec() const {return v;}
                                void set_vec(const Vec3d& vec) {v = vec;}
                private:
                  Vec3d                 v;
};

struct vec3d_to_py
{
static PyObject* convert(const Vec3d& src)
{
  return Py_BuildValue("(ddd)", src[0], src[1], src[2]);
}

static PyTypeObject const *get_pytype () // Could use converter::to_python_target_type
{
  return &PyTuple_Type;
}
};

struct vec3d_from_py
{
  vec3d_from_py()
  {
    boost::python::converter::registry::push_back(
        &convertible,
        &construct,
        boost::python::type_id<Vec3d>()
        );
  }

  static void* convertible(PyObject* obj)
  {
                                return obj;
  }

  static void construct(PyObject* self, p::converter::rvalue_from_python_stage1_data* data)
  {
                typedef p::converter::rvalue_from_python_storage<Vec3d> storage_t;

                storage_t* store = reinterpret_cast<storage_t *>(data);
                void* mem = store->storage.bytes;
                new (mem) Vec3d();

                Vec3d* pv = reinterpret_cast<Vec3d *>(mem);
                PyArg_ParseTuple(self, "ddd", &((*pv)[0]), &((*pv)[1]), &((*pv)[2]));
                data->convertible = mem;
  }
};


BOOST_PYTHON_MODULE(raf)
{
                vec3d_from_py();
                p::to_python_converter<Vec3d, vec3d_to_py, true>();

                p::class_<UseVec3d>("UseVec3d")
                                .def("get_vec", &UseVec3d::get_vec)
                ;
}


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20170404/7be93b98/attachment-0001.html>


More information about the Cplusplus-sig mailing list