[C++-sig] Wrapping opaque pointers returned from API function s

David Abrahams dave at boost-consulting.com
Sun Jan 12 01:05:37 CET 2003


Gottfried,

This is a pretty nice implementation!

However, there are a few slight problems that will show up on very
conformant C++ implementations: firstly, pointer_converter<P>::dealloc
has C++ linkage, so you can't stick it in the tp_dealloc slot, which
has to be a function pointer with 'C' linkage.  Second, a few things
you are doing with pointer_converter depend on it having an initial
section which is layout-compatible with PyObject.  Unfortunately, the
C++ standard doesn't guarantee anything about object layout for
classes with bases, constructors, or private members (non-POD types).
Third, your use of the typename keyword in the declaration of the 'x'
member is illegal.  You can only use typename for dependent types;
paradoxically, template arguments themselves are not dependent.  You
also left out a typename on the execute function.

Finally, I think your DEFINE_POINTER_CONVERTER macro is likely to make
a Python type name containing illegal characters like '*', though I
guess you are passing a typedef here so it's probably not a big deal.

Allow me to suggest the following modification (untested):

<------------->
// convert_opaque_pointer --
//
// usage: convert_opaque_pointer<pointer_type>("name")
//
// registers to- and from- python conversions for a type pointer_type,
// and a corresponding Python type called "name".
//
namespace detail
{
    extern "C" inline void dealloc(PyObject* self)
    {
        PyObject_Del(self);
    }
}

template <class Pointer>
struct convert_opaque_pointer
    : ::boost::python::to_python_converter<
          Pointer, convert_opaque_pointer<Pointer> >
{
    // This is a POD so we can use PyObject_Del on it, for example.
    struct instance
    {
        PyObject_HEAD
        Pointer x;
    };

    convert_opaque_pointer(char const* name)
    {
        type_object.tp_name = name;

        boost::python::lvalue_from_pytype<
            opaque_pointer_converter, &opaque_pointer_converter::type
        >();
    }

    static PyObject* convert(Pointer x)
    {
        instance *o = PyObject_New (instance, &type_object);
        o->x = x;
        return boost::python::detail::upcast<PyObject>(o);
    }

    static typename boost::remove_pointer<Pointer>::type&
    execute(instance &p_)
    {
        return *p_.x;
    }

    static PyTypeObject type_object;
};

template <class Pointer>
PyTypeObject convert_opaque_pointer<Pointer>::type_object =
{
    PyObject_HEAD_INIT(NULL)
    0,
    0,
    sizeof(typename convert_opaque_pointer<Pointer>::instance),
    0,
    detail::dealloc
};
<------------->

After we settle on something, I'd like to put it in the library, or at
least in the FAQ.

Gottfried.Ganssauge at HAUFE.DE writes:

> ...
>> # include "pointer_converter.h"
>
> that implementation worked only in that toy example, as soon as I added a
> second converter it botched.
> Here is a better one
>

<snip>
-- 
                       David Abrahams
   dave at boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution





More information about the Cplusplus-sig mailing list