[C++-sig] extending a c++ object by overriding it's virtual functions..

David Abrahams dave at boost-consulting.com
Wed Jun 28 14:40:59 CEST 2006

Kleistereimer <kleistereimer at gmx.de> writes:

> hi dave,
> thankyou for your explanations and sourcecode.
> i have some more questions about it thought.
> first here is the sourcecode again:
> //Python
>>>> class Derived(Base):
> ...     def f(self):
> ...         return 42
>>>> base = Base()
>>>> derived = Derived()
>>>> base.f()
> 0
>>>> derived.f()
> 42
> //C++ code from your answer
>>1: // substitute the module name where "derived" is defined for "__main__"
>>2: python::object module = python::import("__main__");
>>3: python::object derived = module.attr("derived");
>>4: python::object b = derived( /* arguments to __init__ here */ );
>>5: int result = b.f();


   int result = b.attrib("f")();

> 1)
> the mentioned include file <boost/python/import.hpp> is not in boost
> 1.33.1. where can i get it? is it in cvs? 

Yes.  Get the RC_1_34_0 branch.

> does it suffice if i get this
> .hpp file only, or do i need the complete cvs version? 

I can't guarantee it works without the complete CVS

> for now i used the c api.. instead of this line.
> 2)
> what does the above code exactly? i think it instantiates a python
> 'Derived' class to object 'derived', 

No, creates a reference to the Python class object called "derived."  

> so line 3 has to be:
>  3 python::object derived = module.attr("Derived"); //capital 'D'

Your post mixes case ["so i need to hardcode the name of the
instantiated class ('derived')"] so I used lowercase, but if you
define it as Derived, obviously, capitalize.

> and at line 5 'f' is called on this instance. this gives me  a compiler
> error:
> "f is no element of ..::api::object". how to solve this?
> i guess it involves something like:
>  python::call_method<int>(b.ptr(),"f")
> but this fails in arg_to_python.hpp:181
> "cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();"
> how to do it corectly?

   int result = b.attrib("f")();

> 3)
> so this scheme is not 'overwriting c++ virtual functions with python

I assume you mean "overriding"

> code' directly, instead it's 'deriving a python class from a c++ class,
> overwriting  virtual functions, 

One can only override member functions by deriving in C++, so I don't
see where your expectations for a more "direct" overriding could come

> and then making an instance of this python class and access it from
> c++' right?

That's what you seemed to be wanting to do.

> this means if i have some heavily used c++ class which needs only some
> minor functions tweakable from python, i should better do it like so:
> class py_MyClass:
> 	def Log(self):
> 		...		
> class MyClass
> {
> 	MyClass() {m_PyObject = Instantiate("py_MyClass");} //using line 3 and 4
> 	~MyClass() {delete m_PyObject;}
> 	...
> 	...
> 	void Log(std::string) {python::call_method<void>(m_PyObject, "Log"); }
> };
> because this calls into python only if one of the 'pythonized' functions
> is needed (which is seldom) but not if other c++ functions are used
> (which is extremely often)
> did i understood it right?

Not really.  If you want to use derived polymorphically from C++, you
can also do this:

    python::object d = derived( /*args*/ );
    Base& b = python::extract<Base&>( d );

Now only the functions you've made overridable in Python (e.g. f) will
use any part of the Python API at all, and those that aren't actually
overridden will only do a fast lookup, find nothing, and continue with
C++ code, without interpreting any bytecode.

Dave Abrahams
Boost Consulting

More information about the Cplusplus-sig mailing list