被dll折腾了很长一段时间,上网查了很多资料,终于搞清楚了,现把dll的编写和使用方法进行梳理一下,分享给大家,也方便自己以后随时查询。另外把我看到的两篇有价值的参考文章贴出来,我的这篇文章是在它们的基础上,加上自己的实践总结出来的。
链接1:http://blog.chinaunix.net/uid-20255102-id-1713076.html
链接2:http://www.blogjava.net/wxb_nudt/archive/2007/09/11/144371.html
我们在编写好一个系统软件后,有时需要更新该软件的某一部分代码,修改完成后我们需要再次编译该系统软件,这很不方便。有没有方法只修改该部分代码,而不用重新编译该系统软件呢?另外,当一段程序需要在其他语言中使用时,需要重写该段代码,这同样影响工作效率,有没有方法让我们可以直接使用该段代码呢?dll的出现可以很好的解决这些问题。
根据以上描述,可将优点总结如下:
1. dll可供多种语言直接调用。
2.当一个系统软件使用了dll文件,如果需要修改该dll,只需要将修改后的dll替换原dll,不需要重新编译整个系统软件。
3.节省内存。当一段代码以源代码的形式在不同程序间重用时,同时运行这些程序的exe,系统会在内存中重复加载这段代码。若使用dll来编写这段代码,则只会在内存中加载一次,所有使用该dll的进程会共享这段内存。
使用VS2010制作dll时,默认生成的即是该方式。VS2010制作dll方式如下:
(1). 打开【VS2010】--->【新建项目】--->选择【win32控制台应用程序】,输入项目名称,选择保存路径后,点击【确定】。如下图所示:
(2). 点击【确定】后,弹出【win32应用程序向导】界面;点击【下一步】,弹出【应用程序设置】界面,【应用程序类型】选择【DLL】,【附加选项】选择【导出符号】,点击【完成】。如下图所示:
(3). 点击【完成】后生成一个如下图所示的工程文件:
我们只需要关注DllTest.h、DllTest.cpp这两个文件。DllTest.h文件给出了导出函数的声明示例,参照该示例可以声明自定义的导出函数;函数定义写在DllTest.cpp文件中,如下图所示:
该文件自动给出了导出函数的示例,我们可以参照该示例定义所需要的导出函数。
(4). 函数声明和定义完成后,点击【启动调试】,启动成功后,弹出如下图所示的界面:
此时,我们在该路径下即可看到已生成DllTest.dll文件和DllTest.lib文件。
在调用该方式制作的dll时,需使用DllTest.h文件、DllTest.dll文件和DllTest.lib文件。
(1). 采用def文件方式时,不需要DllTest.h文件。因此将上述工程中的头文件从工程中移除,(因为stdafx.h文件内包括window.h,所以将dllmain.cpp文件内的#include
(2). 在源文件中添加【新建项】,选择【模块定义文件(.def)】,输入好名称后,点击【添加】,如下图所示
添加好后的工程如下图所示:
此时就可以在DllTest.def文件内定义声明导出函数了(定义导出函数和第一种方式一样,在DllTest.cpp内定义)。具体格式链接1的文章中所讲,如下图所示:
(1). 格式如下:#pragma comment(lib,"DllTest.lib");
在调用程序内必须写上#include"DllTest.h"
(2). 隐式调用时,调用该dll的程序只能是C或C++
采用隐式调用上面生成的dll文件的代码示例如下图所示:
显示调用需要先用Loadlibrary函数加载dll文件,然后用GetProcAddress找到该dll的地址,采用显示调用dll的示例代码如下图所示:
从以上可知:制作dll有两种方式,调用dll也有两种方式。这样在使用时就有4种组合方式。
以下给出了这四种组合方式使用方法和示例代码。
上面讲到调用时有4种组合方式,下面具体来讲一讲这四种方式的使用方法(末尾给出代码示例链接):
步骤一:首先将dll制作好后的头文件、dll文件、lib文件拷贝到调用该dll的工程中。
步骤二:用教程一中隐式调用的方法将dll加载到该工程内即可。
注意:这种方式必须在制作dll的头文件内,在导出函数前添加上extern "C"。因为如果不加的话,C++编译器考虑到函数的重载,会将dll中的函数名进行更改(可以使用dumpbin命令验证添加extern "C"前后是否发生变化)。这导致在使用dll过程中,使用GetProceAddress查找导出函数时必须使用更改后的函数名,很不方便。
步骤一:只需将dll制作好后的dll文件拷贝到调用该dll的工程中。
步骤二:用教程一中的显示调用的方法将dll加载到该工程即可。
步骤一:将制作好的dll文件和lib文件拷贝到调用该dll的工程中。
步骤二:由于def方式没有头文件,所以在调用程序中首先声明导出函数,再按照教程一中的隐式调用方法进行调用即可。
注:该方式不会出现方式二中所说的函数名被更改的问题
步骤一:将dll制作好后的dll文件拷贝到调用该dll的工程中。
步骤二:用教程一中的显示调用的方法将dll加载到该工程即可。
dll制作和调用代码示例