在Windows API函数声明中,“CALLBACK”是什么意思?

14

可能是重复问题:
C中的“CALLBACK”声明是什么意思?

WindowProc()函数的原型如下:

LRESULT CALLBACK WindowProc(HWND hWnd,UINT message , WPARAM wParan, LPARAM lParam);

但我从未遇到过 CALLBACK 关键字,我只知道回调函数是将指向另一个函数的指针传递给它的函数,那么这里的 CALLBACK 到底是什么?它有什么作用?

1个回答

15

这是因为Win32 API默认使用回调函数的__stdcall调用约定。调用约定描述了函数调用在低层级别上的安排方式,包括参数如何在CPU堆栈中排列等。调用方和被调用方之间关于预期堆栈布局(即调用约定)的假设必须匹配,否则可能会出现各种问题。

历史上,在Intel CPU上有多个调用约定;如果计算非Microsoft编译器,则更多。如果计算能够调用Windows API并被其调用的其他语言,情况更加复杂。确保将Windows API回调明确标记为__stdcall以符合WinAPI的期望是一种好习惯。在某些情况下,具体取决于编译器和设置,__stdcall是默认的调用约定(即可以安全地省略CALLBACK),但并非总是如此。

在Win16时代,CALLBACK被定义为far pascal。这甚至不太可能成为用户函数的默认值,特别是在C程序中。回调函数被假定具有Pascal调用约定是一种历史文物。它也作为微优化工作。


什么是_stdcall?由于LRESULT是返回类型,_stdcall是什么?它在声明中占据什么位置?并且,您能简单地解释一下它回调到什么吗? - Ghost
1
__stdcall表示一种调用约定,其中之一。回调是一种技术,API调用您的函数而不是相反。为了正确执行此操作,API需要知道您的函数遵循的调用约定。 - Seva Alekseyev
我们如何改变调用约定?WinProc函数是否也以某种方式遵循约定(这不是有道理的吗,因为我们告诉Windows要遵循哪个约定,这意味着WinProc与约定相关联)?抱歉提了一堆问题,我还没有完全满意。 - Ghost
3
你可以更改函数的调用约定。查找关键字__cdecl、__thiscall和__fastcall。但是,如果该函数将被不属于你的代码(即Windows代码)所调用,则你声明的约定必须与其将要被调用的约定相匹配。这是__stdcall,因为Windows假定如此。在Windows头文件中,__stdcall已经被别名为CALLBACK,以方便你使用。 - Seva Alekseyev
1
为了完整起见,需要注意的是,在为x64编译的代码中,“CALLBACK”已经不再相关(https://dev59.com/Ybzpa4cB1Zd3GeqPCwMA) - René Nyffenegger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接