动态链接库(DLL)和静态库(lib)
2016-12-21 15:55
267 查看
一、 静态链接库与动态链接库区别
静态链接库与动态链接库都是共享代码的方式
lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了,可以删除静态库文件;
DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。
另一个区别在于:
静态链接库中不能再包含其他的动态链接库或者静态库;
而在动态链接库中还可以再包含其他的动态或静态链接库。
动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。如果在当前工程中有多处对dll文件中同一个函数的调用,那么执行时,这个函数只会留下一份拷贝。但是如果有多处对lib文件中同一个函数的调用,那么执行时,该函数将在当前程序的执行空间里留下多份拷贝,而且是一处调用就产生一份拷贝。
二、静态链接库(lib)
1.在 VS 中新建一个 Win32 项目静态库程序 addDLL
2.添加一个头文件addlib.h 一个源文件addlib.cpp。将要把下面这个函数封装为动态链接库提供给第三方:
编译这个工程就得到了一个 addDLL.lib 文件,这个文件就是一个函数库,它提供了add 函数的功能。将头文件 addlib.h 和 addDLL.lib 文件提供个给用户后,用户就可以直接使用其中的 add 函数了。
3.调用静态库:新建一个工程 libtest,仅包含一个 main.cpp 文件,其源代码如下:
注意:需要将
addlib.h 和 addDLL.lib 文件放到当前工程目录下,或者包含文件的绝对路径。
如果不用 #pragma comment 指定,则可在 vs 中添加的 addDLL.lib 文件的路径,如下图:
4.库文件的调试
由于库文件不能单独执行,调试和查看库文件较好的方法是:将库工程和应用工程(调用库的工程)放置在同一工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点,执行后按下 F11,这样就单步进入了库中的函数。上述调试方法对静态链接库和动态链接库而言是一致的。
三、动态链接库(DLL)
在 vs 中新建一个 DLL 类型的空项目 add
在建立的工程中添加 addDLL.h 及 addDLL.cpp 文件,源代码如下:
addDLL.h 对函数 add 的声明前面添加了 __declspec(dllexport) 语句,声明函数 add 为 DLL 的导出函数。编译上面的工程,生成文件中包含文件 add.dll 和 add.lib 。
动态库调用:新建一个测试工程,并将文件 add.dll 和 add.lib 放到工程的目录中,同时新建一个 main.cpp 文件:
四、DLL 导出变量
DLL定义的全局变量可以被调用进程访问;DLL也可以访问调用进程的全局数据。在(三)动态链接库中导出了一个全局变量,一个较为安全的使用 DLL 导出的全局变量方法:
通过 _declspec(dllimport) 方式导入的就是 DLL 中全局变量本身而不再是其地址了,建议在一切可能的情况下都使用这种方式。
五、DLL 导出类
DLL中定义的类可以在调用的工程中使用。
在类的声明头文件中用一个宏 DLL_FILE 来决定使其编译为 class _declspec(dllexport) point 还是 class _declspec(dllimport) point 版本。为了简单起见,直接在类的声明中对类函数进行了实现。编译上面的工程,生成库文件。
类的引用
将上面工程文件 point.h 和 生成库文件 point.dll 拷贝到当前工程目录下。
静态链接库与动态链接库都是共享代码的方式
lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了,可以删除静态库文件;
DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。
另一个区别在于:
静态链接库中不能再包含其他的动态链接库或者静态库;
而在动态链接库中还可以再包含其他的动态或静态链接库。
动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。如果在当前工程中有多处对dll文件中同一个函数的调用,那么执行时,这个函数只会留下一份拷贝。但是如果有多处对lib文件中同一个函数的调用,那么执行时,该函数将在当前程序的执行空间里留下多份拷贝,而且是一处调用就产生一份拷贝。
二、静态链接库(lib)
1.在 VS 中新建一个 Win32 项目静态库程序 addDLL
2.添加一个头文件addlib.h 一个源文件addlib.cpp。将要把下面这个函数封装为动态链接库提供给第三方:
//文件:addlib.h #ifndef ADDLIB_H #define ADDLIB_H extern "C" int add(int x,int y); //声明为C编译、连接方式的外部函数 #endif //文件:addlib.cpp #include "addlib.h" int add(int x,int y) { return x + y; }
编译这个工程就得到了一个 addDLL.lib 文件,这个文件就是一个函数库,它提供了add 函数的功能。将头文件 addlib.h 和 addDLL.lib 文件提供个给用户后,用户就可以直接使用其中的 add 函数了。
3.调用静态库:新建一个工程 libtest,仅包含一个 main.cpp 文件,其源代码如下:
#include <stdio.h> #include "addlib.h" //包含头文件 #pragma comment(lib, "addDLL.lib") //指定与静态库一起连接 int main(int argc, char* argv[]) { printf( "2 + 3 = %d", add( 2, 3 )); getchar(); }
注意:需要将
addlib.h 和 addDLL.lib 文件放到当前工程目录下,或者包含文件的绝对路径。
如果不用 #pragma comment 指定,则可在 vs 中添加的 addDLL.lib 文件的路径,如下图:
4.库文件的调试
由于库文件不能单独执行,调试和查看库文件较好的方法是:将库工程和应用工程(调用库的工程)放置在同一工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点,执行后按下 F11,这样就单步进入了库中的函数。上述调试方法对静态链接库和动态链接库而言是一致的。
三、动态链接库(DLL)
在 vs 中新建一个 DLL 类型的空项目 add
在建立的工程中添加 addDLL.h 及 addDLL.cpp 文件,源代码如下:
/* 文件名:addDLL.h */ #ifndef ADDLIB_H #define ADDLIB_H extern "C" int __declspec(dllexport)add(int x, int y); extern int value; //导出全局变量 #endif /* 文件名:addDLL.cpp */ #include "addDLL.h" int value; //定义一个全局变量 int add(int x, int y) { return x + y; }
addDLL.h 对函数 add 的声明前面添加了 __declspec(dllexport) 语句,声明函数 add 为 DLL 的导出函数。编译上面的工程,生成文件中包含文件 add.dll 和 add.lib 。
动态库调用:新建一个测试工程,并将文件 add.dll 和 add.lib 放到工程的目录中,同时新建一个 main.cpp 文件:
#include <stdio.h> #include <windows.h> typedef int(*pAddFun)(int, int); //宏定义函数指针类型,与函数 add 类型一致 int main(int argc, char *argv[]) { HINSTANCE hDll; //DLL句柄 pAddFun addFun; //函数指针 hDll = LoadLibrary("add.dll"); //加载指定动态链接库的地址 if (hDll != NULL) { addFun = (pAddFun)GetProcAddress(hDll, "add"); //返回指定动态连接库中指定输出函数的地址 if (addFun != NULL) { int result = addFun(2, 3); printf("2 + 3 = %d", result); } FreeLibrary(hDll); //释放链接库 } return 0; }
四、DLL 导出变量
DLL定义的全局变量可以被调用进程访问;DLL也可以访问调用进程的全局数据。在(三)动态链接库中导出了一个全局变量,一个较为安全的使用 DLL 导出的全局变量方法:
#include <stdio.h> #pragma comment(lib,"add.lib") //链接静态库 extern int _declspec(dllimport) value; //用 _declspec(dllimport) 导入 DLL 中的全局变量 int main(int argc, char *argv[]) { printf("%d ", value); value = 1; //可以直接使用, 无须进行强制指针转换 printf("%d ", value); return 0; }
通过 _declspec(dllimport) 方式导入的就是 DLL 中全局变量本身而不再是其地址了,建议在一切可能的情况下都使用这种方式。
五、DLL 导出类
DLL中定义的类可以在调用的工程中使用。
//文件名:point.h,声明 point 类 #ifndef POINT_H #define POINT_H #ifdef DLL_FILE class _declspec(dllexport) point //导出类 point #else class _declspec(dllimport) point //导入类 point #endif { public: point() : x(0.0), y(0.0) {} point(float x_c, float y_c): x(x_c), y(y_c) {} float add() { return x + y; } private: float x; float y; }; #endif
在类的声明头文件中用一个宏 DLL_FILE 来决定使其编译为 class _declspec(dllexport) point 还是 class _declspec(dllimport) point 版本。为了简单起见,直接在类的声明中对类函数进行了实现。编译上面的工程,生成库文件。
类的引用
将上面工程文件 point.h 和 生成库文件 point.dll 拷贝到当前工程目录下。
#include "point.h" //包含类声明头文件 #pragma comment(lib,"point.lib"); //链接静态库 int main(int argc, char *argv[]) { point p(2.0, 2.0); // 直接使用类 point printf("p(2.0,2.0).add() = %f \n", p.add()); // 使用类的函数 return 0; }
相关文章推荐
- Windows核心编程---动态链接库(XX.dll)与静态库(XX.lib)
- 静态库Lib和动态库Dll
- VC环境下的静态库(lib)使用和动态库(Dll)的使用(清晰版)
- 什么叫程序库什么是lib,什么是dll,什么是.a,什么是.so,什么是静态库,什么是动态库
- 静态链接库LIB和动态链接库DLL的区别 创建和示例
- .h头文件 .lib动态链接库文件 .dll 动态链接库
- windows中静态库lib和动态dll的区别及使用方法
- 静态链接库LIB和动态链接库DLL的区别 创建和示例
- 通过lib对动态链接库DLL进行引用的项目,发布时DLL放置的位置
- lib和dll 动态链接库 静态链接库 等的介绍
- 关于lib,dll,.a,.so,静态库和动态库的解释说明
- 静态链接库LIB和动态链接库DLL的区别
- 生成读取相关连接的物理地址的lib(动态导入库)和dll(动态链接库)
- 动态链接库dll,静态链接库lib, 导入库lib
- 转:DLL动态链接库和LIB静态链接库之程序员分析
- 动态链接库dll 静态链接库lib 动态导入库lib
- 静态链接库LIB和动态链接库DLL的区别
- 查看静态库(.lib)和动态库(.dll)的导出函数的信息
- 查看静态库(.lib)和动态库(.dll)的导出函数的信息
- .h头文件 .lib动态链接库文件 .dll 动态链接库