[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