changing argument value in a C++/Python code -
my problem follow: have c++ code can't modify want (not written me , under intellectual property constraints). have link python code through python main. use boost::python reflection. @ point in code, c++ function use python overloaded function of c++ function modify parameter. function works great when used inside python. when called c++ function, modification of parameter not taken account while in c++. model problem, wrote simplified version aimed @ isolating problem.
here c++ classes:
#include <iostream> using namespace std; #include <boost/ref.hpp> //class aimed @ modeling c++ user's type should used in python class c { public: double myc; c(){} ~c(){} void setvalue(double val) { myc = val; } double getvalue() { return myc; } }; /* class derived in python want sure that: - void (g) , non void (f) functions reflected , extended in python - function (h) local type (c) use python overloaded function of c++ function (g) */ class { public: a(){int a_x=0;} virtual ~a(){} virtual int f(int ivar){ ivar = 0; return ivar; } virtual void g(c * myc){ c calledc; cout << "i should not here" << endl; //when b::setparam call g, should python g, not virtual function base class calledc.setvalue(0.); //return *myc; } c h(){ //this function wont overloaded in python c myc; //myc.setvalue(0.); this->g(&myc); //we want myc modified, , python overloaded version of g used cout << "value in c++: " << myc.getvalue() << endl; //we want verify if myc has been modified in c++ return myc; } }; /* class called main in python. it's function setparam aimed @ ensuring python extension of c++ class supported */ class b { public: b(a & a){ setparam(a); } b(){ int u; u = 0; } virtual ~b(){} void setparam(a & a){ a.h(); //here code should call h overloaded function of derived class of in python } };
the boost::python wrapper:
#include <boost/python.hpp> #include <python.h> #include <object.h> #include "classa.h" #include <boost/python/module.hpp> #include <boost/python/def.hpp> #include <boost/python/implicit.hpp> #include <iostream> using namespace std; using namespace boost::python; /* wrapper used allow overload of virtual function */ struct wrapperclassa : a, boost::python::wrapper<a>{ int f(int ivar){ if(override f = this->get_override("f")){ return f(ivar); } else { return a::f(ivar); } } int default_f(int ivar){ return this->a::f(ivar); } void g(c * myc){ if(override g = this->get_override("g")){ g(myc); } else { a::g(myc); } } void default_g(c * myc){ this->a::g(myc); } }; /* refection of necessary classes , functions python */ boost_python_module(mywrapper){ class_<wrapperclassa, boost::noncopyable>("a", init<>()) .def("f", &a::f, &wrapperclassa::default_f) .def("g", &a::g, &wrapperclassa::default_g) ; class_<b, boost::noncopyable>("b", init<>()) .def("setparam", &b::setparam) ; class_<c>("c", init<>()) .def("setvalue", &c::setvalue) .def("getvalue", &c::getvalue) .def_readwrite("myc", &c::myc) ; }
the python code:
from math import * # c++ library mywrapper import * """ extension of c++ class apy should used when type argument called g should able use c++ c type object , modify constructor call g in order verify myc treated mutable within python """ class apy(a): def __init__(self): a.__init__(self) n = 0 x = 0. myc = c() self.g(myc) print("value after 1st call within python: " + repr(myc.getvalue())) def f(self, n): n = 5 return n def g(self, myc): x = 7.0 myc.setvalue(x) print("value in python: " + repr(myc.getvalue())) """ main myb.setparam should able pass apy argument """ mya = apy() myb = b() myb.setparam(mya)
when run code, print("value in python: " + repr(myc.getvalue())) print 7, cout << myc.getvalue() << endl print 0 while variable @ 7. thank help.
the problem here when convert c
instance python in call g(myc)
, boost.python uses by-value converter rather shallow converter (i.e. copies c
instance), though you've passed pointer.
this design: when pass c++ pointer python, boost.python ensure python code doesn't have worry other c++ code deleting while python layer still has access it, lead dangerous memory errors. way ensure copy object.
if you'd force boost.python pass myc
object reference, use g(boost::python::ptr(myc))
(or g(boost::ref(*myc))
if know it's not null), aware dangerous; need make sure python implementation of g()
doesn't try hold onto argument beyond lifetime.
you can find more information here:
http://www.boost.org/doc/libs/1_48_0/libs/python/doc/v2/callbacks.html
you can use boost::shared_ptr
pass arguments python without copying in safe way:
Comments
Post a Comment