您的位置:首页 > 其它

编写和使用DLL时,常用的关键字 extern "C",__declspec,__cdecl,__stdcall

2011-05-17 17:14 423 查看
extern "C",__declspec,__cdecl,__stdcall

extern "C" 是告诉编译器的编译方式;

__cdecl和__stdcall是指函数的调用规范;

__declspec一般用来声明DLL中函数的导入导出;

1.先说extern "C"

C和C++的编绎器对函数名译码的方式不同所引起。如果同一个函数,在C编绎器是通过函数名来识别的,而在C++中,由于存在函数的重载问题,函数的识别方式通函数名、函数的返回类型和函数参数列表三者组合来完成的。同一个函数,经过C,C++编绎后会产生完全不同的函数名字。所以,如果把一个用C编绎器编绎的目标代码和一个用C++编绎器编绎的目标代码进行连接,就会出现连接失败的错误。解决的方法是使用extern "C",它告诉C++编绎器按照C++的方式去编绎C函数。

举例:
extern "C" int strlen(char* string)
或者
extern "C"
{
int strlen(char* string)
}

2.再说__cdecl和__stdcall

__cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要注意了,只有用相同的方法才能够调用成功.
_cdecl 是C Declaration的缩写,表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
  _stdcall 是Standard Call的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retn X,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。
  _fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。
  PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。

举例:
int __stdcall strlen(char* string);
int __cdecl strlen(char* string);

3.最后说__declspec
__declspec一般都是用来声明DLL中的导入导出函数。如:__declspec(dllexport)和__declspec(dllimport)。这个关键字也有一些其他的用法,不过非常罕见.

如是编写DLL时,有定义DEF文件,则不需使用__declspec(dllexport)。DEF是文本格式,它被用于导出一个DLL的函数,和__declspec(dllexport)很相似 。

举例:
__declspec(dllexport) int strlen(char* string);

组合举例:
extern "C" __declspec (dllexport) int __stdcall strlen(char* string);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: