转载请声明出处!!!谢谢!!!
经常我们需要利用我们以前编写某些程序里面的某些函数,但是我们总不能每次都把原来文件打开然后复制粘贴吧,太麻烦了,有人想到了一些暴力的方法,如果那个文件只是一个实现函数的功能的文件,没有主函数的话,就#include<XXX.c/.cpp>,然后编译相当暴力。明显这样会急剧增大我们最终生成的.exe文件大小。所以我们就要自已写一个库,以后需要的时候然后调用就行了。现在我们就来讨论怎样编写自己的库。
在开始之前先弄明白几个概念:动态链接库、动态链接库、动态链接、静态链接。
静态链接库
通俗说就是不管现在需不需要在生成可执行文件的时候全部编译进去。不管暂时能不能用到,先拿来再说,明显这样生成的可执行文件会很大。这是静态链接库致命的缺点,因为很多软件虽然对大小没有要求但是过分的冗余是让人无法接受的。但是这也是产生静态链接库优点的原因,避免了dll hell的问题。
动态链接库
与静态链接库相反,动态连接库就是在需要的时候才调用。因此动态链接库显得简洁方便,但是产生了 dll hell的问题。什么是dll hell呢?简单的比喻一下。我喜欢吃包子,静态链接库相当于与,为了吃包子我在自己家里开了家包子店,虽然目前不吃,但是想吃的时候就会有,不会产生别人跟我抢包子的现象。动态链接库相当于我家门口开了家包子店,这个包子店不是我家的,每次想吃包子才去包子店,因此节省了我家的地方,但是会产生别人跟我竞争包子的显现,同时今天卖的包子不一定符合我的口味(相当于dll版本不对),更主要的是包子是别人做的啊,安全问题咋办?谁对我有仇包子里面下毒怎么办?因此动态链接库是有一定的风险的。
静态链接
静态链接和动态链接是动态链接库实现的两种方法。静态链接就是直接在程序运行前将需要的运行库包含进来,就跟#define 一样,是原地展开。在程序运行前检查这些库,如果某个库不存在,程序无法运行。
动态链接
动态链接是在程序运行的时候需要了才去加载。例如我有个读取数据库的函数做成了dll,只有当我点击了查找按钮之后,才会加载这个库然后实现某些功能,如果这个库不存在,紧紧是某些功能无法实现,对程序其他功能没有影响。
了解了几个概念之后,开始介绍怎样编写和应用DLL文件
1、编写dll文件。
打开VC 新建工程,选择win32 Dynamic link library选项。工程名为:MyFirstDll如下图
2、选择一个简单的工程,点击完成。
3、为做简单演示,实现一个两个数相加功能的函数。打开MyFirstDll.cpp文件,添加如下代码extern "C" _declspec(dllexport) int add(int a,int b)
{
return a+b;
}其中extern "C" _declspec(dllexport)不必关心,照写就行。其实这是声明了后面那个add函数是符合C语言规范的一个dll调用接口。后面那个函数就是自己定义的函数。添加之后如下图
4、点击组建->全部组建就行。
现在我们的dll问价就做好了,在工程的debug文件夹下面我们发现生成了对应的MyFirstDll.lib和MyFirstDll.dll文件。怎样使用呢?
一、静态加载
很多人编程序都喜欢在程序中静态加载Windows提供的一些库,我们自己生成的库调用方式是一样的。只需添加添加如下代码即可
#pragma comment(lib,"MyFirstDll.lib")
extern "C" _declspec(dllexport) int add(int i1,int i2);
效果如下:
执行结果如下:
注意:要将我们生成的MyFirstDll.lib和MyFirstDll.dll文件拷贝到我们当前工程下,不然是无法运行的。
二、动态加载
动态链接的实现方法相当于指针的用法,开始定义一个函数指针,然后找到我们需要的dll文件,然后加载,找到我们需要的函数,将该函数的地址传递给我们定义的函数指针,然后使用我们的函数指针进行操作。函数指针定义如下:
typedef int(_cdecl* FunctionAdd)(int,int);
动态加载在需要的时候才加载,采用询问方式进行模拟,询问用户是否加载dll,当用户输入Y之后加载dll文件然后执行。实现如下
执行效果如下图:
这样我们自己的dll文件就使用成功了!!!