假设我有一些未指定的类型,称为 variant
,以及两个允许与此类型相互转换的函数,具有以下签名:
struct converter
{
template<typename T>
static variant to(const T&);
template<typename T>
static T from(const variant&);
};
现在,我想做的是为任意 C++ 函数创建包装器,如下例所示:
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)));
}
理想情况下,我希望包装器是一个单行声明或宏,仅将 f_unwrapped
函数和名称 f
作为输入。
我尝试将函数包装到一个函数对象中,然后使用可变参数模板进行官僚工作。虽然这确实有效,但我不知道如何生成结果函数 extern "C"
。
实现此目标最惯用的方法是什么?
最佳答案
如果我们使用前两个代码块中的 EVAL、helper、Conditional 和 map 宏 here .
为了满足我们的需要, map 需要变得更加通用。
#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)
我们还需要 WithTypes
和 WithoutTypes
来自 here .
我们可以定义AMACRO
做你想做的工作。
#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) \
)
这会变成:
AMACRO(SomeObject,f,(const std::string&, s, int*, x))
{
// ... do something with the inputs ...
return SomeObject();
}
进入这个(格式化后):
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();
}
注意:
如果const
需要从参数中删除一个条件,类似于 ISDONE
, 可以制作并添加到 ConvertFrom
宏。
关于c++ - C++ 函数的自动 C 包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44012984/