一、LIB和DLL介绍
DLL:动态链接库(dynamic link library)
LIB:有两种情况:
1)一种是LIB仅包含索引信息(函数所在的DLL文件和文件中函数位置的信息)且无实现,代码由运行时加载在进程空间中的DLL提供
2)一种时LIB既包含索引也包含实现(函数代码本身),在编译链接时直接将代码加入程序当中
注:
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装载。
二、使用准备
1、使用静态Lib依赖的文件:
1).h头文件(包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中)
2).LIB静态库(该库应该既包含索引也包含实现)
2、使用动态Dll依赖的文件:
1).h头文件(包含dll中说明输出的类或符号原型或数据结构的.h文件。应用程序调用dll时,需要将该文件包含入应用程序的源文件中)
2).LIB文件,是dll在编译、链接成功之后生成的文件,作用是当其他应用程序调用dll时,需要将该文件引入应用程序,否则产生错误。
如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载
3).dll文件,真正的可执行文件,开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,并不需要.lib文件和.h头文件。
三、使用说明
1、静态库LIB的使用
1)静态库LIB生成
创建工程-》win32 project-》选择 static Library
//test.h
void testPrintf(void);
//test.cpp
void testPrintf(void)
{
printf("testStaticLib printf\r\n");
}
最后编译生成。
2)静态库LIB使用
2.1)引入头文件
#include "test.h"
2.2)引入库
通过代码引入:#pragma comment(lib, "testStaticLib.lib")
通过配置引入:
2.3)实际使用
testPrintf();
2、动态库DLL的使用
1)动态库DLL生成
创建工程-》win32 project-》选择 DLL
//DllLibTest.h
#ifdef DLLLIBTEST_EXPORTS
#define DLLLIBTEST_API __declspec(dllexport)
#else
#define DLLLIBTEST_API __declspec(dllimport)
#endif
#if 0
// This class is exported from the DllLibTest.dll
class DLLLIBTEST_API CDllLibTest {
public:
CDllLibTest(void);
// TODO: add your methods here.
};
extern DLLLIBTEST_API int nDllLibTest;
DLLLIBTEST_API int fnDllLibTest(void);
#endif
extern "C" DLLLIBTEST_API void testDllPrintf(void);
//DllLibTest.cpp
#include "stdafx.h"
#include "DllLibTest.h"
#if 0
// This is an example of an exported variable
DLLLIBTEST_API int nDllLibTest=0;
// This is an example of an exported function.
DLLLIBTEST_API int fnDllLibTest(void)
{
return 42;
}
// This is the constructor of a class that has been exported.
// see DllLibTest.h for the class definition
CDllLibTest::CDllLibTest()
{
return;
}
void CDllLibTest::testDllPrintf(void)
{
printf("testDllPrintf\r\n");
return;
}
#endif
DLLLIBTEST_API void testDllPrintf(void)
{
printf("testDllPrintf\r\n");
return;
}
2)动态库接口导出有两种方式:
2.1)采用__declspec
extern "C" __declspec(dllexport) void testDllPrintf();
说明:
C++在编译时,会对函数名进行处理,也就是说Test函数也许会变成Test@1等形式.为了避免这个情况,我们需要采用extern "C"关键字,用来告诉编译器,这个函数采用C语言的编译方式,
一方面在Dll中Test会以原名出现,另一方面也让C程序能够调用C++编写的Dll库.而__declspec(dllexport)则是告诉编译器,我们这个函数要作为对外接口.
2.2)采用def文件
注:使用隐式链接的话可以不用extern ”C“
注:使用隐式链接和显式链接都会执行到DllMain。
最后编译生成。
3)动态库DLL使用
3.1)静态加载
3.1.1)引入头文件
#include "DllLibTest.h"
3.1.2)引入库
通过代码引入:#pragma comment(lib, "DllLibTest.lib")
通过配置引入:通过properties->Linker->input->Additional Dependence中添加
3.1.3)实际使用
testDllPrintf();
3.2)动态加载
//main.cpp
#include <stdio.h>
#include "test.h"
//#include "DllLibTest.h"
#include <windows.h>
//#pragma comment(lib, "testStaticLib.lib")
//#pragma comment(lib, "DllLibTest.lib") 该静态加载也可以通过properties->Linker->input->Additional Dependence中添加
typedef void (*DLL_TEST)(void);
void main(void)
{
printf("hello world\r\n");
testPrintf();
HINSTANCE hInstDll = LoadLibrary(TEXT("DllLibTest.dll"));
if(hInstDll == NULL)
{
FreeLibrary(hInstDll);
}
//获取Dll函数地址
DLL_TEST DllPrintf = (DLL_TEST) GetProcAddress(hInstDll,"testDllPrintf");
if (DllPrintf == NULL)
{
FreeLibrary(hInstDll);
}
//testDllPrintf();
DllPrintf();
getchar();
FreeLibrary(hInstDll);
return;
}
//DllLibTest.h
#ifdef DLLLIBTEST_EXPORTS
#define DLLLIBTEST_API __declspec(dllexport)
#else
#define DLLLIBTEST_API __declspec(dllimport)
#endif
#if 0
// This class is exported from the DllLibTest.dll
class DLLLIBTEST_API CDllLibTest {
public:
CDllLibTest(void);
// TODO: add your methods here.
};
extern DLLLIBTEST_API int nDllLibTest;
DLLLIBTEST_API int fnDllLibTest(void);
#endif
extern "C" DLLLIBTEST_API void testDllPrintf(void);
如果没有extern "C"会出现以下问题:
Unhandled exception at 0x00000000 in testWin.exe: 0xC0000005: Access violation.
需要在编译库的时候就加上extern “C”
注:使用动态加载的话只需要.DLL库就可以,即不需要.LIB库和.h文件
四、静态库Lib和DLL的区别
1、static lib在link之后可以直接运行使用,dynamic lib还需要相应的dll配合
2、static lib需要建立工程进行编译,dynamic lib是编译Dll自动生成的附加产物
3、static lib没有函数入口点,也就是说,并没有类似于WinMain或DllMain的函数,简单的说,只是函数的一个集合而已
4、static lib包含索引和实现,dynamic lib只包含索引
五、总结
1、static lib使用需要.h、在模块中或代码中加入.Lib和将.Lib拷入工程目录
2、DLL使用
2.1)隐式链接
.h头文件、.Lib和DLL库放到工程目录,在代码中引入.h头文件和Lib库说明
2.2)显式链接
采用WIN32 API函数LoadLibrary、GetProcAddress装载。不需要.h和.Lib,只需要.DLL文件