[C++-sig] To-/From-Python converters for shared_ptr types

Dominic Sacré dominic.sacre at gmx.de
Wed May 16 02:54:21 CEST 2012


Hi,

I have written custom converters from Python to C++ types and vice versa. 
Now I'd like to wrap C++ functions that expect/return shared pointers to 
those types.

I could of course write another set of converters for each type, but that 
would mean duplicating a lot of code for no good reason. Is there a simple 
way to generate converters for shared_ptr<T>, if converters for T already 
exist?

See below for a simple test case. From Python I can call test.foo(42) and 
get back the same value. Calling test.bar(42) fails, because there's no 
converter from int to shared_ptr<Test>. What's the easiest way to make 
bar() behave the same way as foo()?


Thanks in advance,

Dominic


--- test module ---

#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>

namespace bp = boost::python;

struct Test {
    int value;
};

struct test_from_python_converter {
    test_from_python_converter() {
        bp::converter::registry::push_back(
                &convertible, &construct, bp::type_id<Test>());
    }
    static void *convertible(PyObject *obj) {
        return PyInt_Check(obj) ? obj : 0;
    }
    static void construct(PyObject *obj,
                bp::converter::rvalue_from_python_stage1_data *data) {
        void *storage = (reinterpret_cast<bp::converter::
                rvalue_from_python_storage<Test>*>(data))->storage.bytes;
        new (storage) Test();
        ((Test *)storage)->value = bp::extract<int>(obj);
        data->convertible = storage;
    }
};

struct test_to_python_converter
  : bp::to_python_converter<Test, test_to_python_converter, true>
{
    static PyObject *convert(Test const & t) {
        return PyInt_FromLong(t.value);
    }
    static PyTypeObject const *get_pytype() {
        return &PyInt_Type;
    }
};

Test foo(Test t) {
    return t;
}

boost::shared_ptr<Test> bar(boost::shared_ptr<Test> pt) {
    return pt;
}

BOOST_PYTHON_MODULE(test) {
    test_from_python_converter();
    test_to_python_converter();

    bp::def("foo", &foo);
    bp::def("bar", &bar);
}


More information about the Cplusplus-sig mailing list