[C++-sig] problems with typedef void *

Jim Bosch talljimbo at gmail.com
Sun Dec 12 23:04:31 CET 2010


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


More information about the Cplusplus-sig mailing list