I followed the test examples that I found on the web, and I am able to replicate the examples.
My issue occurs when I:
1)
Write a C++ base class
2)
Wrap this C++ base class in C++
3)
Inherit from this wrapped C++ class in python
4)
Then try to use this python inherited class as an argument into a different C++ function expecting the C++ base class I created in step 1.
I have attached the C++ and py code.
My C++ code:
#include <string>
#include <map>
#include <iterator>
#include <iostream>
#include <iosfwd>
#include <boost/python.hpp>
using namespace boost::python;
namespace // unnamed
{
struct Base
{
virtual ~Base() {};
virtual int f() const = 0;
};
struct BaseWrap : Base, wrapper<Base>
{
virtual ~BaseWrap() {}
int f() const
{
return this->get_override("f")();
}
};
void functionWithBaseArgument(Base & baseObj)
{
std::cout << "You have successfully called 'functionWithBaseArgument'" << std::endl;
std::cout << "Value: " << baseObj.f() << std::endl;
}
class classWithBaseMember
{
public:
classWithBaseMember (const Base & baseObj) : baseObj_(baseObj) {}
void test() const
{
std::cout << "You have successfully called 'classWithBaseMember::test': " << std::endl;
int d = baseObj_.f();
std::cout << "Value: " << d << std::endl;
}
private:
const Base & baseObj_;
};
class DoubleVector // empty stub class
{
public:
DoubleVector() {}
DoubleVector(int s, double v) {}
~DoubleVector() {}
};
class DoubleMatrix // empty stub class
{
public:
DoubleMatrix() {}
DoubleMatrix(int nr, int nc, double v) {}
~DoubleMatrix() {}
};
class MathSmoothFunction
{
public:
MathSmoothFunction() {}
virtual ~MathSmoothFunction() {}
virtual double value(const DoubleVector& currentPoint) const = 0;
virtual DoubleVector gradient(const DoubleVector& currentPoint) const = 0;
virtual DoubleMatrix hessian(const DoubleVector& currentPoint) const { return DoubleMatrix(); }
private:
};
class PyWrapSmoothFunction : public MathSmoothFunction, public wrapper<MathSmoothFunction>
{
public:
PyWrapSmoothFunction() {}
virtual ~PyWrapSmoothFunction() {}
virtual double value(const DoubleVector& currentPoint) const
{
return call<double>(this->get_override("value").ptr(),currentPoint);
}
virtual DoubleVector gradient(const DoubleVector& currentPoint) const
{
return call<DoubleVector>(this->get_override("gradient").ptr(),currentPoint);
}
virtual DoubleMatrix hessian(const DoubleVector& currentPoint) const
{
return call<DoubleMatrix>(this->get_override("hessian").ptr(),currentPoint);
}
private:
};
class classWithBaseMember2
{
public:
classWithBaseMember2 (const MathSmoothFunction& baseObj) : baseObj_(baseObj) {}
void test()
{
std::cout << "You have successfully called 'classWithBaseMember2::test': " << std::endl;
//std::cout << "Value: " << value( DoubleVector(1,-5.0) ) << std::endl;
}
private:
const MathSmoothFunction& baseObj_;
};
} // end namespace unnamed
void init_pyivm()
{
class_<DoubleVector>
("DoubleVector")
.def(init<>())
.def(init<int, double>())
;
class_<DoubleMatrix>
("DoubleMatrix")
.def(init<>())
.def(init<int, int, double>())
;
class_<BaseWrap, boost::noncopyable >
("Base", "Base")
.def("f", pure_virtual(&Base::f))
;
class_<classWithBaseMember, boost::noncopyable>
("classWithBaseMember", "classWithBaseMember", init<const Base&>() )
.def("test", &classWithBaseMember::test)
;
def("functionWithBaseArgument", functionWithBaseArgument);
class_<PyWrapSmoothFunction, boost::noncopyable >
("PyWrapSmoothFunction", "PyWrapSmoothFunction")
.def("value", pure_virtual(&MathSmoothFunction::value) )
.def("gradient", pure_virtual(&MathSmoothFunction::gradient) )
.def("hessian", pure_virtual(&MathSmoothFunction::hessian) )
;
class_<classWithBaseMember2, boost::noncopyable>
("classWithBaseMember2", "classWithBaseMember2", init<const MathSmoothFunction&>() )
.def("test", &classWithBaseMember2::test)
;
}
BOOST_PYTHON_MODULE(_testPyInheritVM)
{
init_pyivm();
}
-------------------------------------------------------------------------------------------
My python code is:
-------------------------------------------------------------------------------------------
#!/usr/bin/python
#
#
import os, sys
import math
from _testPyInheritVM import *
##################################################
# THIS WORKS
##################################################
class Dummy:
def __init__(self):
pass
base = Base()
dummy = Dummy()
class Derived(Base):
def f(self):
return 42
derived = Derived()
derived.f()
functionWithBaseArgument(derived)
cwbm = classWithBaseMember(derived)
cwbm.test()
##################################################
# THIS DOESN'T WORK
##################################################
class MyPySmoothFunction(PyWrapSmoothFunction):
def __init__(self):
pass
def value(self, point):
return 0.0
def gradient(self, point):
return DoubleVector()
def hessian(self, point):
return DoubleMatrix()
myFn = MyPySmoothFunction()
myClassHasAPyWrapSmoothFn = classWithBaseMember2(myFn)
-------------------------------------------------------------------------------------------
The error I get when I run this is:
Traceback (most recent call last):
File "testPyInheritVM.py", line 49, in <module>
myClassHasAPyWrapSmoothFn = classWithBaseMember2(myFn)
Boost.Python.ArgumentError: Python argument types in
classWithBaseMember2.__init__(classWithBaseMember2, MyPySmoothFunction)
did not match C++ signature:
__init__(_object*, (anonymous namespace)::MathSmoothFunction)
-------------------------------------------------------------------------------------------
I have tried various things but can’t seem to get this to work. Any help would be hugely appreciated.
--Liam