Calling convention "defines" without #define

In Microsoft WinDef.h, several #defines are introduced for callbacks:

#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 

Is there a way to do something like this without preprocessor macros? I would like to have something that allows various calling conventions on Unix and Windows, but which, unlike macros, can be placed in names.

I tried "typedef __stdcall test;" but it does not compile.

EDIT is an example of using a script:

 namespace Thread { typedef startRoutineReturnType (startRoutineCallingConvention *startRoutineCallback)(void* pArg); } Thread::startRoutineReturnType Thread::startRoutineCallingConvention startRoutine(void* pArg); 

Thus, startRoutine can confirm the signature of this callback on all platforms, although the calling callback is different between platforms. When it is likely that many functions should confirm this reverse signature, then something like

 #ifdef UNIX void* foo(void* pArg) #elif WINDOWS DWORD WINAPI foo(LPVOID pArg) #else // something else #endif { // body } 

instead, it looks pretty dirty.

+4
source share
1 answer

This is a terrible hack, in my opinion, but I tried to see if I could do it using specialized templates, and it really worked. Try the following:

 #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; } 

It compiles and runs on Visual Studio 2010.

+2
source

Source: https://habr.com/ru/post/1491943/


All Articles