[C++-sig] Issue Overriding C++ virtual methods in boost python for use in other C++ functions

Liam Herron herron at ELLINGTON.com
Fri Jul 8 15:58:09 EDT 2016


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



=============================================================================================
Email transmissions can not be guaranteed to be secure or error-free, as information 
could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or contain 
viruses.  The sender therefore does not accept liability for any errors or omissions in 
the contents of this message which arise as a result of email transmission.  In addition,
the information contained in this email message is intended only for use of the 
individual or entity named above.  If the reader of this message is not the intended
recipient, or the employee or agent responsible to deliver it to the intended recipient,
you are hereby notified that any dissemination, distribution,or copying of this communication,
disclosure of the parties to it, or any action taken or omitted to be taken in reliance on it,
is strictly prohibited, and may be unlawful.  If you are not the intended recipient please
delete this email message. 
==============================================================================================
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20160708/e40bc04a/attachment-0001.html>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: _testPyInheritVM.cpp
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20160708/e40bc04a/attachment-0001.ksh>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testPyInheritVM.py
Type: application/octet-stream
Size: 917 bytes
Desc: testPyInheritVM.py
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20160708/e40bc04a/attachment-0001.obj>


More information about the Cplusplus-sig mailing list