[C++-sig] virtual method issue ?
Adrien Saladin
adrien-ml at wizzi.net
Thu Mar 15 11:51:03 CET 2007
Dear all,
I'm exposing a C++ library to python using boost python.
Almost everything works fine except this:
I have a Minimizer class that needs a "function" object to minimize. These
objects communicates with std::vector<double> and I think the problem is
around there...
I had to (partially) expose std::vector<double> to python because of a lvalue
convertor problem.
The function object is derived from an abstract class "Base".
When I try to redefine the function in python, the std::vector doesn't seem to
be correctly transmitted between objects.
You will find bellow the minimal example I found to reproduce the undesired
feature...
Any advice would be really appreciated !
Thanks,
Adrien
============ C++ CODE ===============
#include <boost/python.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>
#include <boost/python/suite/indexing/indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <iostream>
#include <vector>
#include <cassert>
typedef std::vector<double> Vdouble;
using namespace boost::python;
struct Base
{
virtual ~Base(){};
virtual double Function(const Vdouble& X, Vdouble& Grad)=0;
};
struct BaseWrap: Base, wrapper<Base>
{
double Function(const Vdouble& v, Vdouble& Grad)
{
return this->get_override("Function")(v,Grad);
}
};
struct Minimizer
{
Minimizer(Base& base):_base(base) {
_vec.resize(5); _Grad.resize(5);
for (uint i=0; i<5; i++) {_vec[i]=0.0; _Grad[i]=0.0;} };
void minimize(){
_base.Function(_vec, _Grad);
std::cout << "_Grad[0] =" << _Grad[0] << std::endl;
assert(_Grad[0]>=5.0);
}
//Data:
Base& _base;
Vdouble _vec;
Vdouble _Grad;
};
struct Derived: public Base
{
double Function(const Vdouble& v, Vdouble& grad)
{
grad[0]=12;
return v[0];
}
};
using namespace boost::python;
BOOST_PYTHON_MODULE(minim)
{
class_<std::vector<double> >("std_vector_double")
.def(vector_indexing_suite<std::vector<double> >())
;
class_<BaseWrap, boost::noncopyable>("Base")
.def("Function",pure_virtual(&Base::Function));
class_<Derived, bases<Base> >("Derived")
.def("Function",&Derived::Function );
class_<Minimizer>("Minimizer", init< Base& >() )
.def("minimize", &Minimizer::minimize);
}
========== END C++ CODE ========
compilation:
g++ -o minim.so -shared
minim.cpp -I/usr/include/python2.4 -lboost_python -lpython2.4
========== PYTHON CODE: =========
from minim import *
class PyDerived(Base):
def Function(self, v, grad):
grad[0]=45.0
return 0
pyderived=PyDerived()
v=std_vector_double()
grad=std_vector_double()
for i in range(5):
v.append(0.0)
grad.append(0.0)
derived=Derived()
minim=Minimizer(derived)
minim.minimize() #this one is OK
assert grad[0]>5.0, "grad[0]>5.0" #this one is OK
pyderived.Function(v,grad)
print grad[0]
assert grad[0]==45.0, "grad[0]==45.0" #this one is OK
minim=Minimizer(pyderived)
minim.minimize() # <--- Here I get a C++ assert error (not OK...)
=========== END PYTHON CODE ==================
More information about the Cplusplus-sig
mailing list