链接库总共包括两种:
一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library。共有两种链接方式:
一种是LIB包含函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库static link library。
动态链接使用动态链接库,允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位DLL函数的可执行代码所需的信息。
静态链接使用静态链接库,链接器从静态链接库LIB获取所有被引用函数,并将库同代码一起放到可执行文件中。
关于lib和dll的区别如下:
(1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
(3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。
使用lib需注意两个文件:
(1).h头文件,包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中。
(2).LIB文件,略。
使用dll需注意三个文件:
(1).h头文件,包含dll中说明输出的类或符号原型或数据结构的.h文件。应用程序调用dll时,需要将该文件包含入应用程序的源文件中。
(2).LIB文件,是dll在编译、链接成功之后生成的文件,作用是当其他应用程序调用dll时,需要将该文件引入应用程序,否则产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。
(3).dll文件,真正的可执行文件,开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,并不需要.lib文件和.h头文件。
lib库的创建方法
1.创建工程时直接选择lib库
2.工程属性—配置属性—常规—配置类型中选lib库
之后生成,默认在debug目录下生成lib文件,在工程同名文件夹下有相应的头文件
lib库的使用
1.项目-属性-配置属性-VC++目录-包含目录中添加头文件所在目录
2.VC++目录-库目录添加lib文件所在路径
3.在链接器-输入-附加依赖项中添加lib
注意在编写程序时添加头文件
dll的创建
1.创建工程时直接选择dll库
2.工程属性—配置属性—常规—配置类型中选dll库
3.DLL中导出函数的声明有两种方式:
一种为在函数声明中加上 _declspec(dllexport) int add(int a, int b);
对于C的编译器需要添加 extern "C" _declspec(dllexport) int add(int a, int b);
另外一种方式是采用模块定义(.def) 文件声明
def文件的编写
def文件必须包含两个部分LIBRARY和EXPORTS
例子:
LIBRARY DllTestDef
EXPORTS
Add @ 1
Sub @ 2
def文件的规则为:
(1)LIBRARY 后面列出def文件相应的DLL名;
(2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);@后的序号不给出的话系统会自动给出。
def文件的设置
链接器—输入—模板定义文件,若使用VS添加的def则会自动把def添加进去
创建def文件之后,生成,默认在debug目录下生成dll文件与lib文件,在工程同名文件夹下有相应的头文
dll文件的使用
(1)隐式链接
与lib库的使用相同
1.项目-属性-配置属性-VC++目录-包含目录中添加头文件所在目录
2.VC++目录-库目录添加lib文件所在路径
3.在链接器-输入-附加依赖项中添加lib
注意经测试这种情况程序只需要lib,与dll无关?
(2)显式链接
显示链接不需要.h与.lib文件,只需要dll文件,将其放在你的工程文件中即可
#include <windows.h>
typedef void (*DLLFunc)(int);
int main()
{
DLLFunc dllFunc;
HINSTANCE hInstLibrary = LoadLibrary("test.dll");//添加你的dll
if (hInstLibrary == NULL)
{
FreeLibrary(hInstLibrary);
}
dllFunc = (DLLFunc)GetProcAddress(hInstLibrary, "TestDLL");//添加你要运行的函数名
if (dllFunc == NULL)
{
FreeLibrary(hInstLibrary);
}
dllFunc(123);//以其作为函数名直接调用函数
}
LoadLibrary函数利用一个名称作为参数,将dll加载置内存中,获得DLL的实例(HINSTANCE类型是实例的句柄),通常调用该函数后需要查看一下函数返回是否成功,如果不成功则返回NULL(句柄无效),此时调用函数FreeLibrary释放DLL获得的内存。
GetProcAddress函数利用DLL的句柄和函数的名称作为参数,返回相应的函数指针,同时必须使用强转;判断函数指针是否为NULL,如果是则调用函数FreeLibrary释放DLL获得的内存。此后,可以使用函数指针来调用实际的函数,最后使用FreeLibrary函数释放内存。
注意:应用程序如何找到DLL文件?
使用LoadLibrary显式链接,那么在函数的参数中可以指定DLL文件的完整路径;如果不指定路径,或者进行隐式链接,Windows将遵循下面的搜索顺序来定位DLL:
(1)包含EXE文件的目录
(2)工程目录
(3)Windows系统目录
(4)Windows目录
(5)列在Path环境变量中的一系列目录