对于一个初学者来说,对于如下函数定义,一定会有点迷惑。STDAPI DllGetClassObject(){}
也许你会问该函数定义中的STDAPI是什么东东。如果你对此迷惑,那我告诉你在WINNT.h文件中STDAPI宏定义如下:

#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
在MSDN中STDAPICALLTYPE宏有如下定义:
 1 #ifdef _WIN32 // Win32 doesn't support __export
 2   #define STDAPICALLTYPE __stdcall
 3 #else
 4   #define STDAPICALLTYPE __export __stdcall
 5 #endif
 6 
 7 #ifdef __cplusplus
 8   #define EXTERN_C extern "C"
 9 #else
10   #define EXTERN_C extern
11 #endif


由此可知,其实STDAPI只是一个宏定义。而该宏定义由两个宏定义(EXTERN_C和STDAPICALLTYPE)和HRESULT组成。经过预编译,有如下结果:
extern "c" HRESULT __stdcall  
这里,我假设是在Win32情况下进行预编译处理的,所以就没有__export了。同时,定义了__cplusplus,即用C++语法。
extern "C"就不用我来说明了吧。随便一本将c/c++的语法书都会提到的。HRESULT是函数的返回值类型。而__stdcall是一种调用类型(call type)。这才是我想说的东西。
在编程时,也许你会看到函数声明或定义中会出现CALLBACK和WINAPI两个宏。其实,它们也是__stdcall的代名词。看windef.h中的内容:

1 #define CALLBACK __stdcall
2 #define WINAPI __stdcall

那么,除了__stdcall,还有别的调用类型吗?究竟什么是调用类型呢?我的理解是:调用类型就是如何使用函数参数的一种规则。有三种调用类型:__fastcall、__cdecl、__stdcall。
1、__cdecl调用类型:
  这是C的调用规则。对于所有非C++成员函数或未标有__stdcall或__fastcall的函数来说,这是默认调用规则。
2、__fastcall调用类型:
  从字面意思可知,这是一种快速调用。因为CPU的寄存器会被使用来存放函数参数列表中的头几个参数。而剩下参数将被从右至左地推倒堆栈上。被调用函数将从寄存器和堆栈获得函数参数。在x86中,ECX和EDX一般被用来存放开始的参数。在.NET中,为了性能上的快速,就是使用ecx和edx来实现 __fastcall的。
3、 __stdcall调用类型:
  该调用只是通过堆栈来push和pop参数。push参数时,顺序是从右到左。

现在,你应该明白了吧。最后,我带一句。三种调用类型在VC编译器中对应/Gd、/Gr、/Gz三个编译选项。

posted on 2008-12-24 16:30  Evilbaniry  阅读(853)  评论(0编辑  收藏  举报