概念:
1,DLL Dynamic Linkable Library,动态链接库,可以看成一种函数仓库,提供直接拿来用的变量、函数或类。
2,静态链接库lib,动态链接库dll,都是共享代码的方式。如果用静态链接库,lib中的指令直接包含在exe文件中。如果是dll,exe执行时动态的引用和卸载dll,dll与exe是相互独立的。
3,VC++支持三种DLL,分别是非MFC动态库(Non-MFC DLL)、MFC Regular DLL(MFC规则DLL),MFC Extension DLL(MFC 扩展 DLL)
非MFC动态链接库:不采用MFC类库结构,导出函数为标准C接口,能被MFC和非MFC编写的应用程序所调用。
MFC规则DLL:包含继承自CWinApp的类,但无消息循环。
MFC扩展DLL:采用MFC动态连接版本,它只能被用MFC类库编写的应用程序调用。
创建dll
注意:这里指的是创建Non-MFC DLL
第一步:在VC6.0中新建一个 Win32 Dynamic-Link Library。这里新建了一个名叫dllTest的工程(弹出的对话框直接默认下一步就好啦)
第二步:dllTest工程中,添加dll.cpp,dll.h文件,其内容如下:
dll.h
#ifndef DLL_H
#define DLL_H
extern "C" int _declspec(dllexport) add(int x,int y);
#endif
dll.cpp
#include "dll.h"
int add(int x,int y)
{
return x + y;
}
上述代码,实现了一个函数:两个int类型变量相加。在头文件中,用extern “C” int _declspec(dllexport) add(int x,int y); 告诉编译器这个函数是dllexport(dll导出函数)。_declspec 这个标识符很好记住 “decl”are声明+“spec”ial特别的(仅为个人理解,方便记忆)
之后,编译、链接生成dllTest.dll文件。
另一种声明dll导出函数的方式:
用模块定义(.def)文件,同样可以实现该功能。其代码如下
dll.def
LIBRARY dllTest
EXPORTS
add @ 1
dll调用
编译、链接后,会在Debug目录下生成dllTest.dll文件,另外还会生成 dllTest.lib文件(该文件也挺有用的),dll.h文件有时也会用到。
额外说一句:为什么要用到dll?
简单来说:”钱=版权“问题。dll类似一个黑盒,你只能调用其提供的接口。你完全不知道里面的代码是如何实现的,除非DLL提供者愿意让你看源码,否则你只能瞎猜啦。这样就很好的保护了版权(money)的问题。
dll调用有两种方式:动态调用和静态调用。动态:完全由使用者加载和卸载dll。静态:编译系统完成 dll的加载和卸载。下面给出两种方式的 代码,这两种代码就其效果来看,是一样的。
动态:
新建工程,将“dllTest.dll"文件放在工程目录下。
main.cpp
#include "stdio.h"
#include "windows.h"
//函数指针类型
typedef int ( * lpAddFun)(int,int);
int main(int argc, char* argv[])
{
HINSTANCE hDll; //DLL句柄
lpAddFun addFun; //函数指针
//加载dll
hDll = LoadLibrary("dllTest.dll");
if (hDll != NULL)
{
//得到函数地址
addFun = (lpAddFun)GetProcAddress(hDll,"add");
if(addFun!=NULL)
{
int result = addFun(2,3);
printf("%d",result);
}
//释放dll
FreeLibrary(hDll);
}
return 0;
}
静态:
新建工程,将“dllTest.dll和dllTest.lib"文件放在工程目录下。
main.cpp
#include "stdio.h"
#include "windows.h"
//加入lib文件
#pragma comment(lib,"dllTest.lib")
//声明导入的函数 dllimport
extern "C" _declspec(dllimport) add(int x,int y);
int main(int argc, char* argv[])
{
int result = add(2,3);
printf("%d",result);
return 0;
}
lib文件中,包含了dll导出函数的符号名及序号(就是数字,比如数字1)。静态调用,就是通过调用lib中的函数符号,再由编译系统自动调用dll中对应的函数符号,完成对函数的使用。
那么头文件(如本例中的 dll.h)有什么用呢?
答:dll不仅可以用在函数上,还可以用在类上。在生成dll的 头文件中,包括对类或函数的声明。新建工程中,导入该头文件,可以很方便的调用知道有哪些函数或者成员函数(类)。而函数具体如何实现,放在dll中。