惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Vercel News
Vercel News
F
Fortinet All Blogs
月光博客
月光博客
G
Google Developers Blog
博客园 - Franky
GbyAI
GbyAI
The Cloudflare Blog
I
InfoQ
雷峰网
雷峰网
WordPress大学
WordPress大学
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
小众软件
小众软件
腾讯CDC
B
Blog
量子位
V
V2EX
S
SegmentFault 最新的问题
Google DeepMind News
Google DeepMind News

博客园 - Stone_石头

硬件检测你用哪一款工具呢? 软件分享:超级兔子2010最新版的九大功能 百度网站打不开,百度域名服务器涉嫌被黑客攻击! 转载:Google管理员工具中抓取错误的解决方法 关于酷狗音乐2010版安全检测的报告 Visual SourceSafe 入门教学 Javascript 解析,格式化日期 (转) PHP技术(转) 用C#生成随机中文汉字验证码的基本原理(转) 不知道该写些什么 把CL和EditPlus进行到底 《DirectShow实务精选》免费下载啦! __declspec(dllexport)的意思与DEF导出函数的区别 #ifdef __cplusplus 倒底是什么意思? - Stone_石头 Rose病毒在校园泛滥,请大家注意! ASP.NET 数据库连接错误 Timeout..... COM学习笔记之IUNKNOWN 感谢各位兄弟的支持 大学生,该怎么过(转载)
晚上写程序的时候就是不知道STDAPI这些东西是搞什么的,分享...
Stone_石头 · 2006-09-26 · via 博客园 - Stone_石头

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

#define STDAPI                  EXTERN_C HRESULT STDAPICALLTYPE
在MSDN中STDAPICALLTYPE宏有如下定义:
#ifdef _WIN32   // Win32 doesn't support __export
   #define STDAPICALLTYPE     __stdcall
#else
   #define STDAPICALLTYPE     __export __stdcall
#endif

#ifdef __cplusplus
   #define EXTERN_C     extern "C"
#else
   #define EXTERN_C     extern
#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中的内容:

#define CALLBACK    __stdcall
#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三个编译选项。