[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