在Microsoft的WinDef.h中引入了几个用于回调的#defines:
#ifdef _MAC
#define CALLBACK PASCAL
#define WINAPI CDECL
#define WINAPIV CDECL
#define APIENTRY WINAPI
#define APIPRIVATE CDECL
#ifdef _68K_
#define PASCAL __pascal
#else
#define PASCAL
#endif
#elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
#else
#define CALLBACK
#define WINAPI
#define WINAPIV
#define APIENTRY WINAPI
#define APIPRIVATE
#define PASCAL pascal
#endif
有没有办法在没有预处理器宏的情况下做这样的事情?
我想有一些东西,解决了Unix和Windows上的不同调用约定,但是 – 与宏不同 – 可以是命名空间.
我试过“typedef __stdcall test;”但那不会编译.
编辑 – 这是一个示例使用场景:
namespace Thread
{
typedef startRoutineReturnType (startRoutineCallingConvention *startRoutineCallback)(void* pArg);
}
Thread::startRoutineReturnType Thread::startRoutineCallingConvention startRoutine(void* pArg);
这样startRoutine可以确认所有平台上的回调签名,尽管回调的调用约定在平台之间有所不同.
当有很多功能可能需要确认回调签名时,就像是
#ifdef UNIX
void* foo(void* pArg)
#elif WINDOWS
DWORD WINAPI foo(LPVOID pArg)
#else
// something else
#endif
{
// body
}
相反看起来很乱.
最佳答案 在我看来,这是一个可怕的黑客攻击,但我试着看看我是否可以通过模板专业化来实现它并且它确实有效.试试这个:
#include <iostream>
enum CALLCONVENTION
{
STDCALL,
CDECL
};
template <CALLCONVENTION Convention>
void Function()
{
}
template<>
void __stdcall Function<STDCALL>()
{
std::cout << "STDCALL" << std::endl;
}
template<>
void __cdecl Function<CDECL>()
{
std::cout << "CDECL" << std::endl;
}
namespace StdCall
{
void Foo()
{
Function<STDCALL>();
}
}
namespace CDecl
{
void Foo()
{
Function<CDECL>();
}
}
int main(void)
{
Function<STDCALL>();
Function<CDECL>();
StdCall::Foo();
CDecl::Foo();
return 0;
}
它编译并适用于Visual Studio 2010.