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

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

gradle error "Cannot convert the provided notation to a File or URI" -

python - NameError: name 'subprocess' is not defined -