首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

【VC编程技能】动态链接库?1.2用模块导出接口

2012-09-23 
【VC编程技巧】动态链接库?1.2用模块导出接口为什么要用模块(def文件)导出接口呢?第一步,我先从函数调用方式

【VC编程技巧】动态链接库?1.2用模块导出接口
为什么要用模块(def文件)导出接口呢?


第一步,我先从函数调用方式说起,大家都知道函数调用有几种常见的方式,分别是__cdecl,__stdcall(pascall),__fastcall,和thiscall。下面我说一下这几种方式会在那些场合出现和它们的差异:

    __cdecl :(C和C++缺省调用方式)参数压栈顺序,从右到左;栈的清除,由调用者完成;__stdcall:(Win32 API的调用方式,并且WINAPI、CALLBACK和__stdcall都一样)参数压栈顺序,从右到左;栈的清除,由被调者完成;通过第一点和第二点我们知道每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的exe模块要比__stdcall大。因为Win32 API采用这种调用方式,所以目前这种方式调用支持大多数语言。而__cdecl约定调用只适合C语言,另外如果接口函数有可变参数必须用__cdecl约定调用,__stdcall约定不行。__fastcall:(C++Builder默认的调用方式)它的主要特点就是快,因为它是通过寄存器来传送参数的。thiscall:(C++类成员函数调用方式)仅仅应用于 "C++" 成员函数。this 指针存放于 CX 寄存器,参数从右到左压。thiscall 不是关键词,因此不能被程序员指定。

综上 ,我们知道Dll要有良好的共性接口的调用约定应该是__stdcall,而如果只是C来用的话可以约定为__cdecl;


第二步,当我们编写__stdcall形式的接口时,大家都知道C++编译器会对函数名做修改,使我们Dll的共性降低(只能在同一种编译器生成的模块之间调用)。

而通过关键字extern "C" __declspec(dllexport)可以保证__cdecl约定方式的函数名称不被改变,却不能保证__stdcall约定方式的函数。这样我们会因为__stdcall函数名称被修改,不能通过函数名来调用接口函数;


第三步,现在可以回答文章开头的问题了,因为向Dll中引入模块的正好解决了上面的问题(保证__stdcall约定方式的函数名称不变),同时它使接口形式更加清晰,为程序员带来了很大帮助。


第四步,我举个例子验证一下这个结论:关键字extern "C" __declspec(dllexport)可以保证__cdecl约定方式的函数名称不被改变,却不能保证__stdcall约定方式的函数。

    创建Win32DLL工程,工程名:DllCall添加求和函数add和求差函数subtract接口,如下:


第五步,我们来证明向DLL中引入模块是可以解决这个问题的。

    先创建Win32DLL工程,工程名:DllCall1添加求和函数add和求差函数subtract接口,如下:

总的来说,编写动态库函数调用方式推荐__stdcall,接口导出时采用模块导出。


热点排行