关于动态链接库、静态链接库

关于动态链接库、静态链接库1 动态库和静态库的异同点动态链接库 DynamicLinka DLL 它提供一些可以直接使用的变量 类和函数

大家好,欢迎来到IT知识分享网。

一、概述

1、动态库和静态库的异同点

动态链接库(Dynamic Linkable Library,DLL)它提供一些可以直接使用的变量,类和函数。经历了 “无库 — 静态链接库 — 动态链接库” 的历程后,dll 应用十分广泛。

静态链接库和动态链接库都是共享代码。

如果采用静态链链接库(.lib),lib 中的指令最终都会编译到链接该静态库的 exe(或 dll)文件中,发布软件时,只需要发布 exe(或 dll)文件,不需要.lib 文件。但是若使用动态链接库(. dll),dll 中的指令不会编译到 exe 文件中,而是在 exe 文件执行期间,动态的加载和卸载独立的 dll 文件,需要和 exe 文件一起发布。

静态链接库和动态链接库另一个区别是静态链接库不能再包含其他动态链接库或静态链接库,而动态链接库不受此限制,动态链接库中可以再包含其他的动态链接库和静态链接库。

2、相关常识

二、静态库

  静态链接库的后缀是.lib。下面的一个例程将介绍如何生成.lib 文件和如何调用.Lib

1、生成.lib 文件

1)、建立一个空解决方案,方案名称为 StaticLibrary。

关于动态链接库、静态链接库

关于动态链接库、静态链接库

选择 Static library, 取消 Precompiled header

关于动态链接库、静态链接库

3)、在该项目中添加 lib.h 和 Lib.cpp 文件,两个文件代码如下图所示

关于动态链接库、静态链接库

lib.h 文件代码如下:

#ifndef __LIB_H__ #define __LIB_H__ int add(int a,int b); #endif

lib.cpp 文件中提供一个函数,实现两个整数的相加,返回两数的和。代码如下:

#include "lib.h" int add(int a,int b) { return a+b; }

4)、库工程不能单独运行,需要右键点击生成

关于动态链接库、静态链接库

生成成功后,将在解决方案目录的 debug 文件夹中生成一个 StaticLib.lib 文件,该文件就是静态库文件。

2、如何调用.lib 文件

1)、在解决方案里再添加一个项目,项目名称为 StaticLibCall,类型为 Win32,控制台程序,选择空项目。

关于动态链接库、静态链接库

选择 Console application 和 Empty project

2)、在项目源文件文件中添加 main.cpp 文件

#include <stdio.h> #include "lib.h" #pragma comment (lib,"StaticLib.lib")//指定与静态库一起连接 int main() { printf("2+3=%d",add(2,3)); }

3)、将刚刚生成的 StaticLib.lib 文件和 lib.h 两个文件复制到该项目的目录下。(一般使用静态库时必须提供这两个文件,.h 文件提供函数的预定义,而.lib 提供函数的实现)

4)、生成的 exe 文件是可以独立运行的运行程序,lib 文件中的函数实现被链接到 exe 文件中,lib 不再需要了。运行结果如下

关于动态链接库、静态链接库

三、 动态链接库

只介绍一种 DLL(非 MFC DLL)的创建与调用方法,本 Dll 实现的功能与第 2 节介绍的静态库实现的功能一样。

1、如何生成一个 dll 文件

1)、创建 dll 工程的步骤和上面介绍的建立 lib 的步骤一样,仅仅在选择类型时需要选择 dll。建立工程后,添加 DLib.h 和 DLib.cpp 文件

关于动态链接库、静态链接库

1 #ifndef __DLIB_H__ 2 #define __DLIB_H__ 3 4 extern "C" int __declspec(dllexport) add(int a,int b); 5 6 7 #endif

DLib.cpp 文件

1 #include "Dlib.h" 2 3 int add(int a,int b) 4 { 5 return a+b; 6 }

2、如何调用.dll 文件

 1 #include "stdio.h" 2 #include "windows.h" 3 4 typedef int (*lpAddFun)(int ,int );//宏定义函数指针类型 5 6 int main() 7 { 8 HINSTANCE hDll;//DLL 句柄 9 lpAddFun addFun;//函数指针 10 hDll = LoadLibrary(L"DynamicLib.dll");//动态获取dll文件的路径 11 if (hDll!=NULL) 12 { 13 addFun =(lpAddFun)GetProcAddress(hDll,"add");//根据函数名在dll文件中获取该函数的地址 14 if (addFun!=NULL) 15 { 16 int result =addFun(2,3); 17 printf("2+3=%d",result); 18 } 19 20 FreeLibrary(hDll); 21 } 22 return 0; 23 } 24

(2)、静态调用 dll

1)、新建一个工程,命名为 DllStaticCall,添加 main.cpp 文件,并将刚刚生成的 DynamicLib.dll 和 DynamicLib.lib 两个文件拷贝到工程目录下。

main.cpp 代码如下

 1 #include "stdio.h" 2 3 //.lib文件中仅仅是关于其对应DLL文件中函数的定位信息 4 #pragma comment(lib,"DynamicLib.lib") 5 6 extern "C" int __declspec(dllimport) add(int a,int b); 7 8 int main() 9 { 10 int result =add(2,3); 11 printf("2+3=%d",result); 12 scanf("%d"); 13 return 0; 14 }

静态调用不需要使用 Win32API 函数来加载和卸载 Dll 以及获取 Dll 中导出函数的地址,这是因为当通过静态链接方式编译生成程序时,编译器会将.lib 文件中导出函数的函数符号链接到生成的 exe 文件中,.lib 文件中包含的与之对应的 dll 文件的文件名也被编译存储在 exe 文件内部,当应用程序运行过程中需要加载 dll 文件时,windows 将根据这些信息查找并加载 dll,然后通过符号名实现对 dll 函数的动态链接,这样,exe 将能直接通过函数名调用 dll 的输出函数,就像调用程序内部的其他函数一样。

四、 动态链接库的 def 文件

dll 导出函数是前面添加__declspec (impoet) 语句,声明该函数为 dll 的导出函数,还有另一种方式声明函数为导出函数–通过 def 文件

1、如何使用 def 文件

(1)新建解决方案,添加两个项目,DllLib 是生成 dll 文件的项目,Dllcall 是调用该 dll 的项目。

(2)在 dllLib 中添加 lib.cpp 和 dlllib.def 两个文件(不需要.h 头文件),代码如下
Lib.cpp 代码:声明两个函数,加法和减法

1 int __stdcall Add(int numa, int numb) 2 { 3 return (numa + numb); 4 } 5 6 int __stdcall Sub(int numa, int numb) 7 { 8 return (numa - numb); 9 }

dllLib.def 代码如下:

1 LIBRARY DllLib 2 EXPORTS 3 Add @ 1 4 Sub @ 2

2、调用 dll

 1 #include <stdio.h> 2 #include <windows.h> 3 4 typedef int (__stdcall *FUN)(int, int); 5 HINSTANCE hInstance; 6 7 FUN fun; 8 9 int main() 10 { 11 hInstance = LoadLibrary(L"DllLib.dll"); 12 if(hInstance!=NULL) 13 { 14 fun = (FUN)GetProcAddress(hInstance, "Add"); 15 //当在Def文件中指定函数序号时,可以通过序号导出,否则只能通过函数名称导出 16 //fun = (FUN)GetProcAddress(hInstance, MAKEINTRESOURCE(1)); 17 if (fun!=NULL) 18 { 19 printf("1+2=%d",fun(1, 2)); 20 } 21 } 22 FreeLibrary(hInstance); 23 return 0; 24 }

注:def 文件中定义了函数序号,在动态加载 dll 时,可以根据这个序号加载函数,这样做的好处时,当 dll 工程的导出函数的函数名有变化,而功能没有变化时,只要 def 中定义的函数序号没有变化,则调用 dll 的代码不需要任何改变。

五、 DllMain 函数

1、为 dll 添加 DllMain 函数

(1)新建解决方案,添加两个工程。一个是生成 dll,一个是调用 dll。

关于动态链接库、静态链接库

Lib.h 代码

1 #ifndef __LIB_H__ 2 #define __LIB_H__ 3 extern "C" int __declspec(dllexport) add(int a,int b); 4 #endif

Lib.cpp 代码

 1 #include "lib.h" 2 #include "stdio.h" 3 #include "windows.h" 4 5 BOOL APIENTRY DllMain(HANDLE hModule, 6 DWORD ul_reason_for_call, 7 LPVOID lpReserved) 8 { 9 switch (ul_reason_for_call) 10 { 11 case DLL_PROCESS_ATTACH: 12 printf("\nprocess attach of dll"); 13 break; 14 case DLL_THREAD_ATTACH: 15 printf("\nthread attach of dll"); 16 break; 17 case DLL_THREAD_DETACH: 18 printf("\nprocess detach of dll"); 19 break; 20 case DLL_PROCESS_DETACH: 21 printf("\nprocess detach of dll"); 22 break; 23 } 24 return TRUE; 25 } 26 27 int add(int a,int b) 28 { 29 return a+b; 30 }

Main.cpp 代码

 1 #include "stdio.h" 2 #include "windows.h" 3 4 typedef int (*lpAddFun)(int ,int );//宏定义函数指针类型 5 6 int main() 7 { 8 HINSTANCE hDll;//DLL 句柄 9 lpAddFun addFun;//函数指针 10 hDll = LoadLibrary(L"DllLib.dll");//动态获取dll文件的路径 11 if (hDll!=NULL) 12 { 13 addFun =(lpAddFun)GetProcAddress(hDll,"add"); 14 if (addFun!=NULL) 15 { 16 int result =addFun(2,3); 17 printf("\ncall add in dll %d",result); 18 } 19 20 FreeLibrary(hDll); 21 } 22 return 0; 23 }

六、 导出类

point.h

 1 #ifndef __POINT_H__ 2 #define __POINT_H__ 3 4 #ifdef DLL_FILE 5 class _declspec (dllexport) point //导出类point 6 #else 7 class _declspec(dllimport) point //导入类point 8 #endif 9 { 10 public: 11 float y; 12 float x; 13 point(); 14 point(float x_coordinate,float y_coordinate); 15 }; 16 17 #endif

point.cpp

 1 #ifndef DLL_FILE 2 #define DLL_FILE 3 #endif 4 #include"point.h" 5 //类point的缺省构造函数 6 point::point() 7 { 8 x=0.0; 9 y=0.0; 10 } 11 point::point(float x_coordinate,float y_coordinate) 12 { 13 x=x_coordinate ; 14 y=y_coordinate; 15 }

circle.h

 1 #ifndef __CIRCLE_H__ 2 #define __CIRCLE_H__ 3 #include "point.h" 4 #ifdef DLL_FILE 5 class _declspec (dllexport) circle //导出类circle 6 #else 7 class _declspec(dllimport) circle //导入类circle 8 #endif 9 { 10 public: 11 void SetCenter(const point crePoint); 12 void SetRadius(float r); 13 float GetGirth(); 14 float GetArea(); 15 circle(); 16 private: 17 float radius; 18 point center; 19 }; 20 21 #endif

circle.cpp

 1 #ifndef DLL_FILE 2 #define DLL_FILE 3 #endif 4 #include"circle.h" 5 #define PI 3. 6 //类circle的缺省构造函数 7 circle::circle() 8 { 9 center =point(0,0); 10 radius =0; 11 } 12 //得到圆的面积 13 float circle::GetArea() 14 { 15 return PI*radius*radius; 16 } 17 //得到圆从周长 18 float circle::GetGirth() 19 { 20 return 2*PI*radius; 21 } 22 //设置圆心坐标 23 void circle::SetCenter(const point crePoint) 24 { 25 center =crePoint; 26 } 27 //设置圆的半径 28 void circle::SetRadius(float r) 29 { 30 radius =r; 31 }

将 circle.h,point.h 和生成的.lib 文件放在同级目录

main.cpp

 1 #include "circle.h" 2 #include "stdio.h" 3 4 //.lib文件中仅仅是关于其对应DLL文件中函数的定位信息 5 #pragma comment(lib,"DllExportClass.lib") 6 7 int main() 8 { 9 circle c; 10 point p(2.0,2.0); 11 c.SetCenter(p); 12 c.SetRadius(1.0); 13 printf("area:%f,girth:%f",c.GetArea(),c.GetGirth()); 14 scanf("%d"); 15 return 0; 16 }

结果为

关于动态链接库、静态链接库

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/126639.html

(0)
上一篇 2025-09-17 13:33
下一篇 2025-09-17 14:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信