Automatic C wrappers for C ++ functions
Let's say I have an undefined type called variant
as well as two functions to convert to / from that type with the following signature:
struct converter
{
template<typename T>
static variant to(const T&);
template<typename T>
static T from(const variant&);
};
Now what I would like to do is create wrappers for any C ++ functions like in the following example:
SomeObject f_unwrapped(const std::string& s, int* x)
{
//... do something with the inputs...
return SomeObject();
}
extern "C" variant f(variant s, variant x)
{
return converter::to<SomeObject>(f_unwrapped(converter::from<std::string>(s), converter::from<int*>(x)));
}
Ideally, I would like the wrapper to be a one-line declaration or a macro that only takes a function f_unwrapped
and a name as input f
.
I tried to wrap a function in a function object and then do the bureaucratic work using variadic templates. While this does work, I have no idea how to create the resulting function extern "C"
.
What is the most idiomatic way to achieve this goal?
source to share
If we use the EVAL, helper, Conditional and map macros from the first two code blocks here .
The map needs to be made more general for our needs.
#define MM1() MM_CALL1
#define MM_NEXT1(Macro,a,...) \
IS_DONE(a)( \
EAT \
, \
OBSTRUCT(COMMA)() OBSTRUCT(MM1)() \
) \
(Macro,a,__VA_ARGS__)
#define MM_CALL1(Macro,a,...) \
Macro(a) \
MM_NEXT1(Macro,__VA_ARGS__)
#define MacroMap1(Macro,...) MM_CALL1(Macro,__VA_ARGS__,DONE)
#define MM2() MM_CALL2
#define MM_NEXT2(Macro,a,...) \
IS_DONE(a)( \
EAT \
, \
OBSTRUCT(COMMA)() OBSTRUCT(MM2)() \
) \
(Macro,a,__VA_ARGS__)
#define MM_CALL2(Macro,a,b,...) \
Macro(a,b) \
MM_NEXT2(Macro,__VA_ARGS__)
#define MacroMap2(Macro,...) MM_CALL2(Macro,__VA_ARGS__,DONE)
We also want to WithTypes
and WithoutTypes
from here .
We can determine AMACRO
to complete the desired task.
#define AsVariant(param) variant param
#define ConvertFrom(type,param) converter::from<type>(param)
#define HEADDER(type,func,params) type func ##_unwrapped (WithTypes params)
#define WRAPPER(type,func,params) \
extern "C" variant func (OBSTRUCT(MacroMap1)(AsVariant,WithoutTypes params)) \
{ \
return converter::to< type >(func ## _unwrapped( \
MacroMap2(ConvertFrom,IDENT params) \
)); \
}
#define AMACRO(type,func,params) \
EVAL( \
HEADDER(type,func,params); \
WRAPPER(type,func,params) \
HEADDER(type,func,params) \
)
Which will look like this:
AMACRO(SomeObject,f,(const std::string&, s, int*, x))
{
// ... do something with the inputs ...
return SomeObject();
}
Into this (after formatting):
SomeObject f_unwrapped (const std::string& s , int* x );
extern "C" variant f (variant s , variant x )
{
return converter::to<SomeObject>(f_unwrapped(converter::from<const std::string&>(s),converter::from<int*>(x)));
}
SomeObject f_unwrapped (const std::string& s , int* x )
{
return SomeObject();
}
Note:
If you const
want to remove from a parameter, a conditional, similar ISDONE
, you can make and add to the macro ConvertFrom
.
source to share