在C++中定义回调函数时经常用到下列语句:
typedef void (CALLBACK *callbackfun) (param1, param2, ... , paramN)
在自己写的方法去调用回调函数时,编译器报错。后来发现是方法中缺少了相应的宏定义WINAPI,正确的定义为:
void WINAPI caller(callbackfun myfun1, param2, ... , paramN)
其中,WINAPI和CALLBACK是windows自带的宏定义:
#define CALLBACK __stdcall
#define WINAPI __stdcall
两者的本质是一样的。_stdcall是一种堆栈调用方式,该方式约定函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。而c++的缺省调用方式是_cdcel,这样出错的原因就很明显了,回调函数和caller函数使用了不同调用方式,导致程序无法通过编译。
那么什么时候使用_cdcel和_stdcall呢?
- 在默认情况下,采用__cdecl方式,因此可以省略.
- WINAPI一般用于修饰动态链接库
- CALLBACK仅用于修饰回调函数