On 12/12/2010 01:02 PM, Jacob Davis wrote:
Howdy!

I'm wrapping a C libary with Boost Python and having a really difficult
time with void * typedefs. For example, here's a typedef and the
function header that uses it:

typedef void * EmoEngineEventHandle;
EmoEngineEventHandle EE_EmoEngineEventCreate();

<snip>
There are also functions that pass these typedefs as args, and I expect
I'll have problems with these, too. i.e.:

void EE_EmoEngineEventFree(EmoEngineEventHandle hEvent);

There are a *lot* of these functions in the library I'm wrapping that
use and return void * typedefs. Is there a way to translate the typedefs
to get all of my function wrappers to pass them properly? Failing that,
how do I modify my wrappers to support the typedefs?


Hopefully someone else will have a more elegant solution, because everything I can think of is pretty ugly. Boost.Python is totally based on templates, and the complete lack of truly distinct types is a big problem, because it has no way to know what Python types to map to when all the C++ types are indistinct.

I think you'll want to define a custom wrapper class for each of these typedefs with a distinct type. From your example, it looks like many of these might be similar enough that you could use a template:

----------------------------------------------------

enum VoidTag { EmoEngineEventHandleTag, ... };

template <VoidTag tag, void * (*ctor)(), void (*dtor)(void * )>
struct VoidWrapper : private boost::noncopyable {

    VoidWrapper() : p(ctor()) {}

    ~VoidWrapper() { dtor(p); }

    void * p;

};

typedef VoidWrapper<
    EmoEngineEventHandleTag,
    &EE_EmoEngineEventCreate,
    &EE_EmoEngineEventFree
> EmoEngineEventHandleWrapper;

-----------------------------------------------------

Now, for all the other (non-constructor/destructor) functions that take these, you'll need to write a function wrapper that takes arguments by the wrapper classes, calls the C function, and returns using the wrapper classes (you'll have to think about ownership semantics in that case, of course). Then you can use Boost.Python to wrap the wrapper functions. You might be able to use templates for the function wrappers too, if certain signatures are common enough.

You could also approach this by writing custom Boost.Python call policies, I think, but that would require a lot of advanced Boost.Python-fu.

Finally, I wouldn't normally recommend SWIG, because I think Boost.Python is generally much better, especially for wrapping C++ code. But in this case, since you're wrapping pure C using a lot of opaque pointers, SWIG's approach might be a better fit, since its code generation naturally considers everything an opaque pointer. If you don't have to use Boost.Python for other reasons, it might be worth a look, at least.

Good luck!

Jim Bosch
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to