C++: Callback typedefs with __stdcall in MSVC

2020-08-23 04:47发布

问题:

This typedef:

typedef DWORD WINAPI
(* CM_Open_DevNode_Key)(DWORD, DWORD, DWORD, DWORD, PHKEY, DWORD);

compiles fine in BorlandCpp, however, when I compile it in msvc I have to remove WINAPI (which is just an alias for __stdcall):

typedef DWORD
(* CM_Open_DevNode_Key)(DWORD, DWORD, DWORD, DWORD, PHKEY, DWORD);

Why is this happening? Can I remove the WINAPI part safely?

Update: I had to remove "WINAPI" form the typedef, otherwise I got

 error C2059: syntax error : '('

for the line.

Can you tell me why Borland could compile it with "WINAPI" while Msvc couldn't?

回答1:

I believe on VC++ you need to put the calling convention inside the ()'s Here's an example on MSDN of using a calling convention inside a function pointer typedef.

typedef DWORD (WINAPI * CM_Open_DevNode_Key)(DWORD, DWORD, DWORD, DWORD, PHKEY, DWORD);

This should compile without problem.



回答2:

A function pointer must have information about the calling convention used by the function. If you're pointing to a function that uses the __cdecl calling convention, you must use a __cdecl function pointer. If you're pointing to a function that uses the __stdcall calling convention, you must use a __stdcall function pointer.

Hope this helps.



回答3:

Side note: I believe function signature typedefs should never be expressed as pointer typedefs.

If you had defined CM_Open_DevNode_Key to be non-pointer, any header declaration of a function which is to follow this callback signature could simply have been written as

CM_Open_DevNode_Key myFunc;

rather than an overly verbose / error-prone

DWORD WINAPI myFunc(DWORD, DWORD, DWORD, DWORD, PHKEY, DWORD);

This would allow for much simpler code and much more specific match-up of function signatures, if needed.

Not to mention that pointer typedefs are evil in general since they dis-allow specifying constness of the content being pointed to (infamous example: "const PCHAR" vs. the properly evaluated "const CHAR *").