3

Documentation of PyBindGen says that it is easy to write custom typehandlers for your own data types. However, I didn't find any good examples of writing them. Examples, which are supplied with pybindgen are too basic to understand the details and the documentation is unfortunately almost non-existing. What I need exactly is:

  • Which class(es) I need to use as a base of my converter?
  • Which methods I have to overload to extend or replace specific parts of the binding code?
  • What approach should I use to handle const and non-const parameters?

Is there any complete and well-documented example of adding custom typehandler to pybindgen? May be somebody did this for your own project and may share an approach?

An example of my current binding to better understand what I need. Done with Boost.python currently:

PyObject* System_getXYZ(System* s, int ind, int fr){
  CREATE_PYARRAY_1D(p,3)
  MAP_EIGEN_TO_PYARRAY(v,Vector3f,p)
  v = s->XYZ(ind,fr);
  return boost::python::incref(p);
}   

...
class_<System, boost::noncopyable>("System", init<>())
  ...
  .def("getXYZ", &System_getXYZ)
  ...
;

Method System::XYZ() return an Eigen::Vector3f object. It have to be converted to numpy array without copying its data. It's important because the whole idea is about efficiency. Currently it is done by means of ugly macros:

#define MAP_EIGEN_TO_PYARRAY(_matr,_T,_obj_ptr) \
    if(!PyArray_Check(_obj_ptr)) throw pteros::Pteros_error("NumPy array expected!"); \
    if(PyArray_TYPE(_obj_ptr)!=PyArray_FLOAT) throw pteros::Pteros_error("float NumPy array expected!"); \
    Eigen::Map<_T> _matr((float*) PyArray_DATA(_obj_ptr), \
            (PyArray_DIM((PyArrayObject*)_obj_ptr,0)==PyArray_Size(_obj_ptr)) ? PyArray_DIM(
            (PyArray_DIM((PyArrayObject*)_obj_ptr,0)==PyArray_Size(_obj_ptr)) ? 1 : PyArray_


#define CREATE_PYARRAY_1D(_ptr_obj, _dim1) \
    PyObject* _ptr_obj; \
    { \
        npy_intp _sz_dim1[1];\
        _sz_dim1[0] = _dim1; \
        _ptr_obj = PyArray_SimpleNew(1, _sz_dim1, PyArray_FLOAT); \
    }

It works, but I need to write a wrapper function for every single method, which takes Eigen objects, which is a nightmare to maintain. That's why I want to try PyBindGen and create a convertor there, which adds all the boilerplate code from these macros automatically.

Btw, boost.python converters doesn't help here since they force copying the data.

yesint
  • 145
  • 9
  • You might be interested to use the [boost python library](http://www.boost.org/doc/libs/1_55_0/libs/python/doc/v2/reference.html) to ease your self from messing with the c-api directly. – πάντα ῥεῖ May 18 '14 at 10:49
  • Actually I'm now using Boost.python and I'm looking for alternative. The problem is that Boost.python custom converters are too limited - they always imply copying the data, which I don't want to do for heavy objects. The is also no custom converters for reference params (out params), only for const references. – yesint May 18 '14 at 11:50
  • It might turn out that the c-api allows you no better because of the engines' inner workings with (referenced) objects. – πάντα ῥεῖ May 18 '14 at 11:54
  • I have a working solution now, but it requires writing a C++ wrapper function for every method, which gets the custom type argument. It's ugly and very hard to maintain. – yesint May 18 '14 at 12:14
  • What about putting a sample of what you have [into your question](http://stackoverflow.com/posts/23721004/edit) and ask for ideas making it better? This may give you better results IMHO. – πάντα ῥεῖ May 18 '14 at 12:17
  • I added an example. It seems that nobody knows pybindgen actually :( Will try to ask developers. – yesint May 18 '14 at 16:11

0 Answers0