[C++-sig] custom r-value converters

Nathan Stewart swarfrat at gmail.com
Fri Apr 2 06:51:39 CEST 2010


On Mon, Mar 29, 2010 at 4:31 PM, Roman Yakovenko
<roman.yakovenko at gmail.com>wrote:

> May be I am missing something, but (py++) variable_t class doesn't
> have return_by_value property.
>
> Indeed it doesn't. I was having trouble figuring out how to create a
return_by_value property to pass to the make functions.

>I am not sure. What py++ version do you use
> Can you post small and complete example, of what you are trying to do?

I didn't post an example because it's essentially 'How to Wrap a Custom
String' from the boost.python FAQ in py++.
Here's an example - I'm using py++ 1.0 and trying to wrap the following:
class CustomString
{
   operator=(...)
   string& val;
};

struct TypeOne
{
    CustomString name;
};

struct TypeTwo
{
    CustomString label;
}

In my py++ script, I create the CustomString_to_pystring and
CustomString_from_pystring structs as in the boost.python docs, and register
the converter.
Where I'm getting a bit confused, is do I need to let py++ wrap the
CustomString class, or does the rvalue converter replace that?  I got around
the original property question by having my py++ script iterate through my
TypeN structs and if the type matches CustomString then I do a
property.exlude() and add the code using struct.add_registration_code() for
that property.  At least that generates registration code like this:

bp::class_<TypeOne>("TypeOne")
    .add_property("name",
                         make_getter(&TypeOne::name,
bp::return_by_value_policy<bp::return_by_value>()),
                         make_setter(&TypeOne::name,
bp::return_by_value_policy<bp::return_by_value>()))

Back to the question of wrapping CustomString though, if I exclude it
(thinking that exposing it was somehow messing with the rvalue conversion
stuff), it just segfaults. If I assign to my CustomString, it behaves as a
python string after that point. But until it has been assigned, it shows up
as <module.my.CustomString object at 0xF00...>.

My converters look like this:

struct CustomString_to_python_str
{
    static PyObject* convert(CustomString const& s)
    {
        return
boost::python::incref(boost::python::object(const_cast<CustomString&>(s)).ptr());
    }
};

struct CustomString_from_python_str
{
    CustomString_from_python_str()
    {
        boost::python::converter::registry::push_back(
            &convertible,
            &construct,
            boost::python::type_id<CustomString>());
    }

   static void* convertible(PyObject* obj_ptr)
    {
        if (!PyString_Check(obj_ptr)) return 0;
        return obj_ptr;
    }

    static void construct(PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
    {
        const char* value = PyString_AsString(obj_ptr);
        if (value == 0) boost::python::throw_error_already_set();
        void* storage =
((boost::python::converter::rvalue_from_python_storage<CustomString>*)
data)->storage.bytes;
        new (storage) CustomStringvalue);
        data->convertible = storage;
    }
}; // struct CustomString_from_python_str

And of course in the module init code, they're installed like so:

    boost::python::to_python_converter<CustomString,
CustomString_to_python_str>();
    CustomString_from_python_str();

The property getters & setters don't seem to be helpful or necessary - I
think now this might just be a default ctor initialization issue, but
providing initialization of the C++ class doesn't seem to work - it looks
like my converter is suspect.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20100402/4aa7ae68/attachment-0001.html>


More information about the Cplusplus-sig mailing list