您的位置:首页 > 其它

编写.dll动态链接库

2013-12-23 23:26 211 查看
DLL编程学习

首先要知道,在VC++6.0环境中,在C调用约定和C编译环境下使用_declspec(dllexport)关键字可以导出不带任何修饰符的函数名。

DLL函数的约定有两种:调用约定和函数名修饰约定。

调用约定又分为:_stdcall调用约定, _cdecl(C调用约定)和_fastcall调用约定。

VC++6.0环境默认的调用约定为_cdecl,即C调用约定。你可以通过菜单选项:

工程-->设置-->C/C++-->在“分类”中选择”CodeGeneration”下可以看到”Calling Convention”下的默认设置为”_cdecl”。



下面我们新建一个Win32 DLL 空工程:添加两个MyDll.cpp和MyDll.h文件

//MyDll.cpp内容

#include "MyDll.h"



int Max(int a, int b)

{

return(a>b)? a:b;

}



int Min(int a, int b)

{

return(a>b)? b:a;

}



//MyDll.h内容

#ifndef _MY_DLL_H_

#define _MY_DLL_H_

#if defined __cplusplus

extern "C"

{

#endif



_declspec(dllexport)int Max(int a, int b);

_declspec(dllexport)int Min(int a, int b);



#if defined __cplusplus

}

#endif

#endif

如下图所示:



之后编译链接,无错误,这样一个动态链接库就生成成功了。

回到工程的Debug目录下就可以看到一个.dll动态链接库文件和一个以.lib为后缀的DLL的映像文件。.lib文件在动态链接库进行隐式链接时会用到,它会被当作.dll的替代文件被编译到应用程序中。

下面再来详细说说MyDll.h文件中的代码的含义:

开头两行和最后一行都是为了防止头文件被重包含的预编译指令。

#if defined __cplusplus

extern "C"

{

#endif



#if defined __cplusplus

}

#endif

意思是如果编译环境是C++环境时,即如果定义了__cplusplus(注意前面是两个下划线)。就执行extern “C”{},告诉编译器要在C环境下编译下面的代码。前面说过,只有在C编译环境和C调用约定下才能导出不带任何修饰的函数名。然后在这之间的就是导出函数的声明部分了,如

_declspec(dllexport) int Max(int a, int b);//这里省略了函数约定关键字

关键字_declspec(dllexport)说明是导出函数,导入函数的关键字是_declspec(dllimport)。

当然了,如果你不怕麻烦,也可以这样写:

_declspec(dllexport) int _cdecl Max(int a, intb);

函数调用约定可以通过菜单设置,也可以通过代码进行设置。如果你通过菜单设置的调用约和你用代码设置的调用约定不同,则以代码设置的为准。



现在你就可以在其他的应用程序中调用该动态链接库了,我们在之后的部分再讲。

下面我们可以用VC++6.0给我们提供的工具DEPENDS.exe来查看我们生成的.dll文件导出的函数了。在你的VC++6.0的安装目录的Tools目录下找到DEPENDS.exe工具

可以看到导出的函数名为Max和Min,不带任何的修饰符。



现在我们再回到DLL的工程中将源文件MyDll.cpp中的extern “C”去掉(这样的编译环境就是C++了),或者将调用约定改为_stdcall(去掉源代码中导出函数声明前的_cdecl关键字,通过工程设置调用约定为_stdcall。或将该关键字改为_stdcall),再编译连接。下面是去掉extern “C”的结果。用DEPENDS.EXE打开.dll文件可以看到导出的函数标识符就多了很多修饰符了,包括函数返回类型,函数名,参数类型以及一些标识号等,如下图:



这样如果我们在程序中直接调用该函数就会出现“有无法解析的符号”这样的错误了。



下面我们就写一个控制台应用程序来调用我们刚才生成的动态链接库中的导出函数:新建一个工程,将之前生成的.dll和.lib文件一起拷贝到当前工程的工作目录下。



但是如果我们使用的是含有修饰符的导出函数的.dll文件,就会出现如下的错误:



作者:http://blog.csdn.net/lp310018931
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: