Boost logo

Boost :

From: Ullrich Koethe (koethe_at_[hidden])
Date: 2000-12-11 12:39:16


John Barnard wrote:
>
> Before I ask my question about BPL, let me thank David, Ullrich, and
> all of the contributors and testers of BPL. I've been very impressed
> with it in the short time of being using it.

Thanks a lot.

> Now on to my question/problem: I'm trying to pass an Python subclass
> instance of a C++ abstract class back to C++. I have a Python class
> testPI which is a subclass of the wrapped C++ abstract class LogPI. I
> wish to pass an instance of testPI to a method draw of the wrapped C++
> class StochasticGrid (all of this in Python, of course), where the
> method draw expects a reference to a LogPI object. When I attempt to
> this I get the error message:
>
> RuntimeError: __init__ function for extension class 'LogPI' was never
> called.
>
> indicating the BPL was expecting a constructor for the abstract class
> LogPI. Can you do this in BPL or have I made an error. I've attached
> the relevant C++ and Python code below. I'm using Microsoft VC++ with
> the latest patches on MS 98SE.
>

I think you simply must wrap a constructor for 'LogPI' that can be
called from within Python. This works because BPL will actually
instantiate a 'LogPI_callback' which must not be an abstract class and
thus can be instantiated. (Note that in your example code,
'LogPI_callback' lacked a constructor. Note also that this constructor
must be called from within the Python-constructor - not doing this
caused the error message in your code.) Here is a simple example that
works for me:

    #include "boost/python/class_builder.hpp"
    #include <string>

    struct Abstract
    {
        virtual std::string test() = 0;
    };

    struct Abstract_callback: Abstract
    {
        Abstract_callback(PyObject * self)
        : m_self(self)
        {}

        std::string test()
        {
            return
boost::python::callback<std::string>::call_method(m_self, "test");
        }

        PyObject * m_self;
    };

    extern "C" void initabstract()
    {
        boost::python::module_builder a("abstract");

        boost::python::class_builder<Abstract, Abstract_callback>
            a_class(a, "Abstract");
        a_class.def(boost::python::constructor<>()); // wrap a
constructor
        a_class.def(&Abstract::test, "test");
    }

Then in Python

>>> from abstract import *
>>> class A(Abstract):
    ... def __init__(self, text):
    ... Abstract.__init__(self) # call the base class
constructor
    ... self.text = text
    ... def test(self): # implement abstract
function
    ... return self.text
    ...
>>> a = A("Hello")
>>> a.test()
    'Hello'
>>>

Ulli

-- 
 ________________________________________________________________
|                                                                |
| Ullrich Koethe  Universität Hamburg / University of Hamburg    |
|                 FB Informatik / Dept. of Computer Science      |
|                 AB Kognitive Systeme / Cognitive Systems Group |
|                                                                |
| Phone: +49 (0)40 42883-2573                Vogt-Koelln-Str. 30 |
| Fax:   +49 (0)40 42883-2572                D - 22527 Hamburg   |
| Email: u.koethe_at_[hidden]               Germany             |
|        koethe_at_[hidden]                        |
| WWW:   http://kogs-www.informatik.uni-hamburg.de/~koethe/      |
|________________________________________________________________|

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk