Writing a Python module using C/API and C++ classes -


i new business of writing custom python modules , bit confused how capsules work. use python 2.7.6 system osx installation , try use capsules (as recommended python > 2.7) passing pointers around (before used pycobject that). code not work @ moment , insights how things should handled in principle here. code should define class luscherclm , want able following:

>>> c40=luscher(4,0) >>> >>> c40(0.12) >>> <print result of evaluation> 

first question: @ moment have like:

>>> c40=luscher.init(4,0) >>> >>> c40.eval(0.12) segfault  

my first question therefore: how have modify method table have more operator-style casts instead of member functions init , eval.

however, code has other problems , here relevant part (the underlying c++ class works smoothly, use in production lot):

the destructor:

//destructor static void clm_destruct(pyobject* capsule){     void* ptr=pycapsule_getpointer(capsule,"zetfunc");     zetafunc* zetptr=static_cast<zetafunc*>(ptr);     delete zetptr;     return; } 

the constructor: returns pointer capsule. not know whether correct. because in case when call, clm=luscherclm.init(l,m), clm object pycapsule , has no attribute eval cannot call clm.eval(x) on that. how should handled?

//constructor static pyobject* clm_init(pyobject* self, pyobject *args){     //return value     pyobject* result=null;      //parse variables     unsigned int lval=0;     int mval=0;     if(!pyarg_parsetuple(args,"li",&lval,&mval)){         ::std::cout << "please specify l , m!" << ::std::endl;         return result;     }      //class instance:     zetafunc* zetfunc=new zetafunc(lval,mval);     instancecapsule=pycapsule_new(static_cast<void*>   (zetfunc),"zetfunc",&clm_destruct);     return instancecapsule; } 

so how capsule passed evaluate function? code below not correct since have not updated after moving cobjects capsules. shall capsule global variable (i not that) or how can pass evaluation function? or shall call on self, self @ moment?

//evaluate function static pyobject* clm_evaluate(pyobject* self, pyobject* args){     //get pycobject capsule:     void* tmpzetfunc=pycapsule_getpointer(instancecapsule,"zetfunc");     if (pyerr_occurred()){         std::cerr << "some error occured!" << std::endl;         return null;     }     zetafunc* zetfunc=static_cast< zetafunc* >(tmpzetfunc);     //parse value:     double x;     if(!pyarg_parsetuple(args,"d",&x)){         std::cerr << "specify number @ want evaluate function" << std::endl;         return null;     }     double result=(*zetfunc)(x).re();      //return result packed function:     return py_buildvalue("d",result); }  //methods static pymethoddef luscherclmmethods[] = {     {"init",  clm_init, meth_varargs, "initialize clm class!"},     {"eval", clm_evaluate, meth_varargs, "evaluate zeta-function!"},     {null, null, 0, null}        /* sentinel */ }; 

python < 3 initialisation function:

pymodinit_func initluscherclm(void) {     pyobject *m = py_initmodule("luscherclm", luscherclmmethods);     return; } 

can explain me wrong , why? stay away swig or boost if possible, since module should portable , want avoid having install additional packages every time want use somewhere else. further: overhead produced c/api in calling function? need call order of o(10^6) times , still fast.

ok, using boost.python segfault when run object.eval(). procedure now:

boost_python_module(threevecd) {     class_< threevec<double> >("threevecd",init<double,double,double>()); }  boost_python_module(luscherclm) {     class_<zetafunc>("luscherclm",init<int,int, optional<double,threevec<double>,double,int> >())     .def("eval",&zetafunc::operator(),return_value_policy<return_by_value>());     boost::python::to_python_converter<dcomplex,dcomplex_to_python_object>(); } 

dcomplex own complex number implementation. had write converter:

struct dcomplex_to_python_object {     static pyobject* convert(dcomplex const& comp)     {         if(fabs(comp.im())<std::numeric_limits<double>::epsilon()){             boost::python::object result=boost::python::object(complex<double>(comp.re(),comp.im()));             return boost::python::incref(result.ptr());         }         else{             return py_buildvalue("d",comp.re());         }     } }; 

complex128 numpy extension not understood boost. questions are: 1) how can return complex number python datatype (is complex standard python type?) 2) why segfault. result in testcase real should default else statement. guess pointer runs out of scope , thats it. in if-case (where take care ref-increments), segfaults. can me type conversion issue?

thanks thorsten

ok, got it. following converter job:

struct dcomplex_to_python_object {     static pyobject* convert(dcomplex const& comp)     {         pyobject* result;         if(std::abs(comp.im())<=std::numeric_limits<double>::epsilon()){             result=pyfloat_fromdouble(comp.re());         }         else{             result=pycomplex_fromdoubles(comp.re(),comp.im());         }         py_incref(result);         return result;     } }; 

using converter , post wouter, suppose question answered. thanks


Comments

Popular posts from this blog

php - failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request -

java - How to filter a backspace keyboard input -

java - Show Soft Keyboard when EditText Appears -