python - Passing a bounded method in Cython as argument -
i trying wrap c++ code cython , came trouble trying pass method class argument function.
i not know if makes more clear, class represents statistical model (so myamethod uses not arguments passed many instance variables) , b has different methods minimizing function passed.
in c++ have of style: class { public: double myamethod(double*) }; class b { public: double mybmethod(a&, double (a::*f) (double*) }
so trying use instances of both , b in cython code. had no trouble wrapping classes, when try use mybmethod, don't know how pass pointer of kind a::*myamethod
if this: mybmethod(ptrtoaobj[0], &ptrtoaobj.myamethod)
, cython compiles code [...] &ptrtoaobj->myamethod [...]
, , message 1 expect g++:
"iso c++ forbids taking address of bound member function form pointer member function."
but if try point straight class method, , mybmethod(ptrtoaobj[0], a.myamethod)
, cython won't compile ,
myamethod not static member a.
and that's pretty able advance. work @ c++ level , avoid of these anoyances, if able use instances of , b in python (via cython) interactively, me in speedig development pace. appreciated, , apologize if question been answered and/or available in referece - search so, cython reference , smith's "cython" book , did not found theme adressed. in advance!
i have partial (if horrendous) solution. i'm prepared believe there's better way, don't know it.
in cpp_bit.hpp:
class { public: double myamethod(double*) { return 0.0; } }; typedef double (a::*a_f_ptr)(double *); class b { public: double mybmethod(a& a, a_f_ptr f) { double x = 0.1; return (a.*f)(&x); } }; a_f_ptr getamethod() { return &a::myamethod; }
i've given functions basic implementations, can check obvious crashes. i've created function pointer returns pointer myamethod
. you'll need every method want wrap.
in py_bit.pyx
# distutils: language = c++ cython.operator import dereference cdef extern "cpp_bit.hpp": cdef cppclass a: double myamethod(double*) cdef cppclass a_f_ptr: pass cdef cppclass b: double mybmethod(a&, a_f_ptr) cdef a_f_ptr getamethod() cdef class pya: cdef a* thisptr def __cinit__(self): self.thisptr = new a() def __dealloc__(self): del self.thisptr cpdef myamethod(self,double[:] o): return self.thisptr.myamethod(&o[0]) cdef class pyb: cdef b* thisptr def __cinit__(self): self.thisptr = new b() def __dealloc__(self): del self.thisptr cpdef mybmethod(self,pya a): return self.thisptr.mybmethod(dereference(a.thisptr),getamethod())
i couldn't figure out how typedef member function pointer in cython, instead created empty cppclass same name. works because cython seems use type-checking , nothing more, , since includes cpp_bit.hpp (where it's defined) can use no problem.
all i've done left task of getting member function pointer c++ (in getamethod
, call). don't think it's entirely satisfactory, looks workable, , short c++ function every member function want access. play put encapsulate more cleanly.
an alternative, untested approach: (edit: further thought suggests might tricky! attempt @ own risk!)
personally, i'd tempted change c++ interface mybmethod
defined as
double mybmethod(std::function<double (double*)>)
(since presumably call a
instance it's passed with). use lambda functions in c++(11!) wrap instance , function
b.mybmethod([&](double* d){ return a.myamethod(d) };
it may take bit of hugely complicated cython wrapping haven't yet considered, should possible convert simple double (double*)
function pointer c++ function object, , use more directly.
it's possible actual design more complicated in ways haven't considered, , approach isn't flexible enough anyway.
Comments
Post a Comment