Passing a polymorphic object from C++ to a python function
Question: I have a C++ library with 2 classes defined in it: **t_foo_base** and
**t_foo**. t_foo is derived from t_foo_base. Both of them implement a virtual
function **text**. This function returns a string with the name of the current
class. I use boost.python to generate a wrapper for this library and for this
classes.

I import this library in a python script. In this script I implemented a
function. This function takes one parameter and call the function "text()" on
it.

Now i import this python script in a C++ application. I use boost.python
again. I get the function "test_function" from the python script and call it
this way:

    
    
    t_foo_base foo_base;
    test_function( foo_base );
    
    t_foo foo;
    test_function( foo );
    
    t_foo_base* foo_base_tpr = new t_foo_base;
    test_function( *foo_base_tpr );
    
    t_foo_base* foo_ptr = new t_foo;
    test_function( *foo_ptr );
    

The outpur is:

> t_foo_base
>
> t_foo
>
> t_foo_base
>
> t_foo_base

**I would expact the 4th line of the output to be "t_foo", not "t_foo_base".**

It seems, that passing a derived object by its base class pointer "cuts away"
all the features of the derived object. Is there a way to do fix this problem?

I am using Visual Studio 2013, Python 3.4 and Boost 1.56.0.

This is code from the C++ library:

\-- file t_foo.h --

    
    
    class __declspec( dllexport ) t_foo_base
    {
    public:
        t_foo_base(){};
    
        virtual ~t_foo_base(){}
    
        virtual std::string text( void ) const { return( "t_foo_base" ); };
    };
    
    
    class __declspec( dllexport ) t_foo: public t_foo_base
    {
    public:
        t_foo(){};
    
        virtual std::string text( void ) const override { return( "t_foo" ); };
    };
    

\-- file t_foo.cpp --

    
    
    #include "t_foo.h"
    
    #include <boost/python.hpp>
    
    using namespace boost::python;
    
    BOOST_PYTHON_MODULE( ex_three_lib )
    {
        class_< t_foo_base >( "t_foo_base" )
            .def( "text", &t_foo_base::text );
        class_< t_foo, bases< t_foo_base > >( "t_simple_callback" )
            .def( "text", &t_foo::text );
    }
    

This is the python script:

    
    
    import ex_three_lib
    
    def test_function( item ):
        print( item.text() )
    
    print( "no function call here" )
    

This is the c++ application:

    
    
    void
    init_module_ex_three_lib
    (
        void
    );
    
    
    boost::python::object
    import_python_object( const std::string& p_name, const std::string& p_path, boost::python::api::object& p_global )
    {
        using namespace boost::python;
        try
        {
            dict locals;
            locals[ "modulename" ] = p_name;
            locals[ "path" ] = p_path;
            exec
            (
                "import imp\n"
                "newmodule = imp.load_module( modulename, open( path ), path,( 'py', 'U', imp.PY_SOURCE ) )\n",
                p_global,
                locals 
            );
            return locals[ "newmodule" ];
        }
        catch( boost::python::error_already_set const & )
        {
            if( PyErr_ExceptionMatches( PyExc_ZeroDivisionError ) )
            {
                assert( false );
            }
            else
            {
                PyErr_Print();
            }
        }
    }
    
    
    
    
    int
    main
    (
    void
    )
    {
        Py_Initialize();
    
        init_module_ex_three_lib();
    
        try
        {
            boost::python::object main_module = boost::python::import( "__main__" );
            boost::python::object main_namespace = main_module.attr( "__dict__" );
    
            {
                boost::python::object script = import_python_object
                (
                    "ex_one_script",
                    "ex_three_script.py",
                    main_namespace
                );
    
                boost::python::object test_function = script.attr( "test_function" );
    
                t_foo_base foo_base;
                test_function( foo_base );
    
                t_foo foo;
                test_function( foo );
    
                t_foo_base* foo_base_tpr = new t_foo_base;
                test_function( *foo_base_tpr );
    
                t_foo_base* foo_ptr = new t_foo;
                test_function( *foo_ptr );
            }
        }
        catch( boost::python::error_already_set const & )
        {
            if( PyErr_ExceptionMatches( PyExc_ZeroDivisionError ) )
            {
                assert( false );
            }
            else
            {
                PyErr_Print();
            }
        }
    }
    


Answer: You should use `boost::ref(...)` here. This will basically convert any
value/pointer to its reference. Also see [Calling Python Functions and
Methods](http://www.boost.org/doc/libs/1_56_0/libs/python/doc/v2/callbacks.html)

    
    
            t_foo_base foo_base;
            test_function( boost::ref(foo_base) );
    
            t_foo foo;
            test_function( boost::ref(foo) );
    
            t_foo_base* foo_base_tpr = new t_foo_base;
            test_function( boost::ref(*foo_base_tpr) );
    
            t_foo_base* foo_ptr = new t_foo;
            test_function( boost::ref(*foo_ptr) );
    

->
    
    
    t_foo_base
    t_foo
    t_foo_base
    t_foo
    

