VS2012下创建和使用DLL (C++)

来源:互联网 发布:js回调函数写法 编辑:程序博客网 时间:2024/05/06 05:17

      什么是dll文件(.dll)?    
      它是应用程序调用dll运行时,真正的可执行文件。dll应用在编译、链接成功后,.dll文件即存在。开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,不必有.lib文件和dll头文件。   
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。 
动态链接与静态链接的不同之处在于:动态链接允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。 
使用动态链接代替静态链接有若干优点。DLL 节省内存,减少交换操作,节省磁盘空间,更易于升级,提供售后支持,提供扩展 MFC 库类的机制,支持多语言程序,并使国际版本的创建轻松完成。 

       好了,上面是我从别人那复制来的解释,我是一个C++的初学者,这两天在网上搜了很多资料才很艰难的学会了在VS以及BCB的开发环境下创建和使用dll,下面我将介绍VS2012下一种很简单的创建和使用dll的方式。这里我只做一些步骤说明以及简单的解释,想更深入的了解dll还是多看看网上大神的资料吧。

       首先,我们需要先写一个程序来生成一个供我们调用的DLL文件,在VS2012开发环境下点击FILE->NEW->Project选择Visual C++下的Win32 Project,给项目起个名字,就叫MyDLL吧,点OK->NEXT 然后选择DLL,点击Finish完成创建,之后我们需呀在MyDLL.cpp下来编写我们需要用到的函数,这里我写了一个加法和一个减法的函数,代码如下:

#include "stdafx.h"#include <iostream>using namespace std;int Add(int plus1, int plus2){int add_result = plus1 + plus2;return add_result;}int Sub(int sub1,int sub2){return sub2 - sub1;}

以上就是我们后面将要使用到的DLL里的方法,可以看出这和平时写方法没有什么区别。


接下来我们需要再写一个.def文件,右击项目名->Add->New Item  选择Code下的Module-Definition File,点击Add完成创建,然后我们会看到内容里面只有一个LIBRARY,这里我们需要自己去增加信息格式很简单,在LIBRARY后面加上名字,再写入EXPORTS关键字,最后列出我们所编写的函数名称以及编号即可。具体代码如下:

LIBRARY "MyDLL"EXPORTSAdd @1Sub @2

这里用微软的官方说明来解释一下def:

模块定义 (.def) 文件是包含一个或多个描述 DLL 各种特性的 Module 语句的文本文件。 如果不使用 __declspec(dllexport) 关键字导出 DLL 的函数,则 DLL 需要 .def 文件。

.def 文件必须至少包含下列模块定义语句:

  • 文件中的第一个语句必须是 LIBRARY 语句。 此语句将 .def 文件标识为属于 DLL。LIBRARY 语句的后面是 DLL 的名称。链接器将此名称放到 DLL 的导入库中。

  • EXPORTS 语句列出名称,可能的话还会列出 DLL 导出函数的序号值。 通过在函数名的后面加上 @ 符和一个数字,给函数分配序号值。当指定序号值时,序号值的范围必须是从 1 到 N,其中 N 是 DLL 导出函数的个数。 

这样我们要写的DLL已经完成了,最后右击项目名,build一下,会发现在我们的项目文件夹下面的Debug文件夹里生成了我们需要的dll文件以及lib文件 。


接下来我们另外创建一个项目去调用这个dll,就创建一个Win32 Console Application项目来测试即可,起个名字叫test,点finish完成,在调用DLL之前我们需要将之前生成的MyDLL,dl文件拷贝到test项目的Debug文件夹里,这里也是生成exe文件的路径,方便我们在代码里面对dll文件进行调用,然后开始在test.cpp文件里写程序来调用我们的DLL,先贴上代码吧:

#include "stdafx.h"#include <iostream>#include <windows.h>#include <string>using namespace std;typedef int(*AddFunc)(int a,int b);HMODULE hModule = NULL;int _tmain(int argc, _TCHAR* argv[]){hModule = LoadLibraryA("MyDLL.dll");//LoadLibraryA的参数是dll文件的路径,直接使用MyDLL.dll是因为我们把dll文件放在了exe相同的目录中if(hModule==NULL){cout<<"LoadLibrary error"<<endl;getchar();return 0;}AddFunc _AddFunc = (AddFunc)GetProcAddress(hModule,"Add");AddFunc _SubFunc = (AddFunc)GetProcAddress(hModule,"Sub");if((_SubFunc == NULL)||(_AddFunc == NULL)){FreeLibrary(hModule);cout<<"GetProcAddress error"<<endl;getchar();return 0;}cout<<"b-a="<<_SubFunc(20,30)<<endl;cout<<"a+b="<<_AddFunc(20,30)<<endl;getchar();FreeLibrary(hModule);return 0;}

其中LoadLibraryA()是载入指定的动态链接库,并将它映射到当前进程使用的地址空间。一旦载入,即可访问库内保存的资源。

GetProcAddress()是,显式链接到 DLL 的进程调用 GetProcAddress来获取 DLL 导出函数的地址。使用返回的函数指针调用 DLL 函数。 GetProcAddress 将(由 LoadLibrary、AfxLoadLibrary 或 GetModuleHandle 返回的)DLL 模块句柄和要调用的函数名或函数的导出序号用作参数。  

注意导出函数失败的时候或者调用结束的时候别忘了用FreeLibrary来释放资源。

完成上面的操作我们再运行程序就可以成功的调用dll里的方法了,至此dll的创建和调用也就完成了。





0 0
原创粉丝点击