[C++-sig] Boost::Python: overriding and smart pointers

Sybren A. Stüvel sybren at stuvel.eu
Wed May 23 16:21:42 CEST 2012


Dear list,

I'm trying to get my head around shared pointers combined with overloaded
methods. I want to create instances of my class both in Python and C++, but
for some reason I can't get both to work with the same code. I've
constructed a minimal example to show you what I'm trying to do. The full
C++ code with syntax highlighting can be found at
http://pastebin.com/ZqG79QUL

Sorry for the long mail, but I saw no other way to show my issues in a
clear and unambiguous way.

--------------------------------------
class ExampleObject {
public:
    std::string name;

    ExampleObject(const std::string & name) : name(name) {}
    virtual ~ExampleObject() {}
    virtual int some_number() { return 12; }
};

typedef boost::shared_ptr<ExampleObject> ExampleObjectPtr;

ExampleObjectPtr create_example_object(const std::string & name) {
    return boost::make_shared<ExampleObject>(name);
}

void print_name(ExampleObjectPtr object) {
    std::cout << "Example object named '" << object->name
        << "', nr = " << object->some_number()
        << std::endl;
}
--------------------------------------

These are the class and functions that I want to wrap. The
ExampleObject::some_number method should be overridable in Python. To this
end, I've created the following wrapper class:

--------------------------------------
struct ExampleObject_wrapper : ExampleObject, wrapper<ExampleObject> {
    ExampleObject_wrapper(const std::string & name)
        : ExampleObject(name), wrapper<ExampleObject>()
    {}

    virtual int some_number(void) override {
        if( override func_override = this->get_override("some_number"))
            return func_override();
        return default_some_number();
    }

    int default_some_number(void) {
        return this->ExampleObject::some_number();
    }
};

typedef boost::shared_ptr<ExampleObject_wrapper> ExampleObject_wrapper_ptr;
--------------------------------------

The Python module is declared as follows:

--------------------------------------
BOOST_PYTHON_MODULE(wraptest) {
    def("create_example_object", &create_example_object);
    def("print_name", &print_name);

    class_<ExampleObject_wrapper, boost::noncopyable, ExampleObjectPtr>
        ("ExampleObject", init<const std::string &>())
        .def("some_number", &ExampleObject_wrapper::some_number,
                            &ExampleObject_wrapper::default_some_number)
    ;
}
--------------------------------------

This is the Python code that I'm testing with:

--------------------------------------
from wraptest import *

class ExampleSubclass(ExampleObject):
    def some_number(self):
        return ExampleObject.some_number(self) * 2

# Test from Python
from_py_obj = ExampleSubclass('from python')
print_name(from_py_obj)

# Test from C++
from_cpp = create_example_object('from C++')
print_name(from_cpp)
--------------------------------------

When I compile the module (VS2010, Python 3.2.2, Boost 1.48) and run the
Python script, I would expect the object created in C++ to show the number
12, and the object created in Python to show the number 24. However, the
output is this:

Example object named 'from python', nr = 12
Example object named 'from C++', nr = 12

Running a debugger also shows that the ExampleObject_wrapper methods aren't
called at all. When I edit the class_<...> line by replacing
ExampleObjectPtr with ExampleObject_wrapper_ptr, the from-Python object
works just fine, but the from-C++ object gives me an exception:

Example object named 'from python', nr = 24
Traceback (most recent call last):
  File "C:\workspace\rage\scripts\test_wrapping.py", line 13, in <module>
    from_cpp = create_example_object('from C++')
TypeError: No to_python (by-value) converter found for C++ type: class
boost::shared_ptr<class ExampleObject>

What should I do to be able to instantiate objects in C++ and Python alike?

Kind regards,
-- 
Sybren A. Stüvel

http://stuvel.eu/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20120523/4f03f995/attachment.html>


More information about the Cplusplus-sig mailing list