链接库动态链接库详细介绍

mysql动态链接库文件 bmysql.dll文件是MySQL的动态链接库文件,缺少此文件数据库无法正常工作。系统文件libmysql.dll是存放在Windows系统文件夹中的重要文件,通常情况下是在安装操作系统过程中自动创建的,对于系统正常运行来说至关重要。 立即下载

作者: 字体:[增加 减小] 类型:转载 时间:2012-11-16 我要评论

静态链接库.lib和动态链接库.dll。其中动态链接库在被使用的时候,通常还提供一个.lib,称为引入库,它主要提供被Dll导出的函数和符号名称,使得链接的时候能够找到dll中对应的函数映射
windows中,链接库分为两种类型:静态链接库.lib和动态链接库.dll。其中动态链接库在被使用的时候,通常还提供一个.lib,称为引入库,它主要提供被Dll导出的函数和符号名称,使得链接的时候能够找到dll中对应的函数映射。 
静态链接库和动态链接库的作用相似,都是提供给其他程序进行调用的资源。其中,动态链接库的调用方法分隐式调用(静态导入调用)和显示调用(动态导入调用)。 

编译环境: 
Microsoft Visual Stdio 2010 
-------------------------------------------------------------------------------- 
DLL导出符号 
例,首先生成一个dll1.dll和dll1.lib 
复制代码代码如下:

// DLL1工程,dll1.cpp 
// _declspec(dllexport)为导出符号 
_declspec(dllexport) int add(int a, int b) 
{ 
return a + b; 
} 

利用微软的depends工具查看dll1.dll,导出的符号如下: 
http://www.cnblogs.com/monotone/ 
其中各字段意义:Ordinal(符号序号,后面使用GetProcAddress的时候,参考的数值),Hint(这个我也不是太明白,据说是不用了解),Function(这个就是函数导出后的符号名称了),EntryPoint(这个是函数在DLL中的地址)。 
这里之所以函数的名称变成了这样子,是因为使用的编译器默认使用C++方式进行编译,由于C++支持重载,那么需要给函数名增加额外的符号,来使与同名的重载函数区分开来,才能在DLL中通过符号名来进行定位。 
这里可以做个简单的测试,新建控制台测试工程DllTest如下。 
复制代码代码如下:

// DllTest工程,DllTest.cpp 
#include <iostream> 
using namespace std; 
int main(void) 
{ 
// extern int add(int a, int b); 
// _declspec(dllimport)是导入声明,这种方式比上面的方式更有效,同时编译器能边编译出更加高效的代码。 
_declspec(dllimport) int add(int a, int b); 
cout << add(1,2) << endl; 
getchar(); 
return 0; 
} 

编译链接,提示链接错误 error LNK2019: unresolved external symbol "__declspec(dllimport) int cdecl add(int,int)" (__imp_?add@@YAHHH@Z) referenced in function _main,很明显的编译器在编译的时候,把add函数也给重命名了,并且和上面用depends查看的一样。意思是没有找到这个符号的定义。 

添加代码后如下:(注意,我这里两个工程的输出目录都是在和解决方案同目录的debug下,为了避免每次修改都重新拷贝lib文件,直接使用相对路径声明。) 
复制代码代码如下:

// DllTest工程,DllTest.cpp 
#include <iostream> 
using namespace std; 
#pragma comment(lib, "../debug/dll1.lib") // 显示的声明要链接dll1.lib,隐式调用 
int main(void) 
{ 
// extern int add(int a, int b); 
// _declspec(dllimport)是导入声明,这种方式比上面的方式更有效,同时编译器能边编译出更加高效的代码。 
_declspec(dllimport) int add(int a, int b); 
cout << add(1,2) << endl; 
getchar(); 
return 0; 
} 

编译运行后,使用depends工具对DllTest.exe查看其依赖的输入信息如下: 
image 
可以看出,DllTest.exe通过dll1.lib,引入了对dll1.dll的依赖。 

-------------------------------------------------------------------------------- 

DLL提供的头文件 
通常情况下,当得到一个.dll的时候,我们无法得知其提供了哪些函数调用(准确来说,应该是调用方式。因为我们可以利用depends工具查看dll导出的函数及其序号,当然也许可能有其他的方式去知道具体怎么使用,但是肯定无法得知内部具体实现细节。),因此为了方便被使用,通常会提供一个对应该dll的.h文件,来声明其提供给客户端使用的方式和说明等信息。客户端使用该头文件对所使用的接口进行导入。但是为了避免很多地方都出现这些函数的声明,通常在客户端直接在.h文件中对所有接口进行导入,而在Dll编译时,则作为导出使用。方法如下: 
复制代码代码如下:

// DLL1工程,dll1.h 
#ifndef DLL1_API 
#define DLL1_API _declspec(dllimport) 
#endif 
// 以上代码表示,如果在包含该头文件之前,没有定义DLL1_API宏,那么后面所有DLL1_API宏都展开为_declspec(dllimport),即导入。 
// 因为通常情况下客户端不会去定义这个宏(当然,假设这个宏不会被客户端中其他文件定义),所以客户端使用该头文件的时候,都是用于导入。 
DLL1_API int add(int a, int b); 

复制代码代码如下:

// DLL1工程,dll1.cpp 
#define DLL1_API _declspec(dllexport) 
// 注意上面这行,在头文件被包含前,先定义了DLL1_API这个宏,使得头文件中DLL1_API都被展开为_declspec(dllexport)了,从而声明函数作为导出。 
#include "dll1.h" 
// 在头文件中进行了导出声明的函数,就不用再声明导出了。 
int add(int a, int b) 
{ 
return a + b; 
} 

相应的,TestDll工程中包含.h文件后,也不用再去申明了。 
复制代码代码如下:

// DllTest工程,DllTest.cpp 
#include <iostream> 
using namespace std; 
#include "../dll1/dll1.h" // 包含该头文件之后,后面就不需要再申明了 
#pragma comment(lib, "../debug/dll1.lib") // 显示的声明要链接dll1.lib,隐式调用 
int main(void) 
{ 
cout << add(1,2) << endl; 
getchar(); 
return 0; 
} 

以上基本解释了为什么通常引用dll的时候都有一个头文件,并且头文件内有很多#ifndef之类的东东了。 

-------------------------------------------------------------------------------- 
动态链接库导出类 
当然,动态链接库也能导出类,要注意的是声明的方式为class DLL1_API CSample,而不是DLL1_API class CSample。 
同时,要注意导出类的同时,其所有成员函数也已经导出,但是仍然遵循类成员变量访问权限限制。 
如果单独导出类的成员函数(声明方式和全局函数一样),那么在客户端可以实例化类对象,并调用导出的成员函数,不能调用没导出的成员函数(即使是public的)。 

-------------------------------------------------------------------------------- 
改编了的符号名 
在导出符号时,讲过C++会对函数名进行改编,以支持函数重载。那么就会存在一个问题,如果使用不用的C++编译器(导致编译出的符号名不同)或者客户端使用C编译器调用,就会出现LNK2019这样的链接错误,找不到符号。这个问题很大的限制了DLL的使用范围。 
解决方法1: 
使用extern “C”(注意这个C一定要大写)前置申明,表明函数是以C的方式编译链接的。C方式编译连接导出的函数不会改编符号名,因而可以避免上述问题。 
复制代码代码如下:

// DLL1工程,dll1.h 
#ifndef DLL1_API 
#define DLL1_API extern "C" _declspec(dllimport) 
#endif 
// 以上代码表示,如果在包含该头文件之前,没有定义DLL1_API宏,那么后面所有DLL1_API宏都展开为_declspec(dllimport),即导入。 
// 因为通常情况下客户端不会去定义这个宏(当然,假设这个宏不会被客户端中其他文件定义),所以客户端使用该头文件的时候,都是用于导入。 
DLL1_API int add(int a, int b); 
//class CSample 
//{ 
//public: 
// DLL1_API int substract(int a,int b);// 这种情况下,导出类成员函数,编译不能通过的 
//}; 

这里要注意.h和.cpp中都要加上extern “C”,使得导入和导出都用C编译方式。 
复制代码代码如下:

// DLL1工程,dll1.cpp 
#define DLL1_API extern "C" _declspec(dllexport) 
// 注意上面这行,在头文件被包含前,先定义了DLL1_API这个宏,使得头文件中DLL1_API都被展开为_declspec(dllexport)了,从而声明函数作为导出。 
#include "dll1.h" 
// 在头文件中进行了导出声明的函数,就不用再声明导出了。 
int add(int a, int b) 
{ 
return a + b; 
} 
// 
//int CSample::substract(int a,int b) 
//{ 
// return a - b; 
//} 

然后用depends进行查看: 
image 
导出的函数符号名和函数声明时一样了。由于客户端使用的时候,导入也是用的extern “C”方式,因此客户端在编译链接的时候,也使用的是函数原名称符号。 
显示,由于使用的是C编译链接方式,C++的类和成员函数的导出就不能用这种方式了。 
此外,如果我们在给函数声明加上标准调用约定:DLL1_API int _stdcall add(int a, int b);(注意,在函数的定义中也要加上_stdcall)。那么编译出来的结果使用depends查看符号名为_add@8,也就是说符号名称又改了。 
解决方法2: 
使用模块定义文件.def,这种文件的格式规范查看MSDN,搜索.def即可。其中LIBRARY命令用于指名该def文件用于导出库文件,EXPORTS用于指名导出函数符号名。也就是说,.def文件主要就用于控制导出符号等信息。 
复制代码代码如下:

LIBRARY dll1 
EXPORTS 
add11=add 

我这里给add函数别名为add11,注意同时需要在.h文件中声明add为add11(作用就是提供给客户端使用,当然其实也可以直接在客户端声明函数为add11,前提是你知道该函数的定义方式等)。一旦提供了.def之后,.cpp中提供的任何调用约定都不再生效,因为.def指定了生成的符号名了。这里只要明白,.def控制了Dll的导出符号,客户端使用的时候,只要提供了声明,并且链接上.lib文件,就能够使用了。 
补充一句:VC6.0以后的IDE都需要在链接选项(LINK)的input-》module define file中,指明.def文件,编译器才会去使用这个.def文件。 

备注: 
这一块关于调用约定,以及加不加extern “C”,目前我还比较混乱。等了解了之后,再来这里进行补充,欢迎看客给我提供有关这一块比较好的介绍资料。 

-------------------------------------------------------------------------------- 
显示链接(动态导入链接) 
前面有提到让导出的函数没有名字,那么客户端如何对其进行调用呢。就是使用符号表中的ordinal了(可以通过工具进行查看),当然也可以使用函数名进行导入。动态导入不需要lib文件和.h文件(如果知道函数名的话)。 
复制代码代码如下:

// DllTest工程,DllTest.cpp 
#include <iostream> 
using namespace std; 
#include <windows.h> 
int main(void) 
{ 
HMODULE hModule = ::LoadLibraryA("dll1.dll"); 
if(NULL != hModule) 
{ 
typedef int (*ADDPROC)(int a, int b); 
//ADDPROC add = (ADDPROC)::GetProcAddress(hModule, "add11"); // 通过函数名导入 
ADDPROC add = (ADDPROC)::GetProcAddress(hModule, MAKEINTRESOURCEA(1)); // 通过ordinal导入,注意第二个参数此时数值要放在低字节位置,具体参见MSDN说明。 
if(NULL != add) 
cout << add(1,1) << endl; 
::FreeLibrary(hModule); 
} 
getchar(); 
return 0; 
} 

值得一提的是,根据函数名称进行动态导入的时候,实际上也是根据符号名的,也就是说,dll提供的符号名要和提供给用户的函数声明一致。

此外,动态导入动态链接库时,.exe时无法查看到需要的输入信息的。 

-------------------------------------------------------------------------------- 
后记 
第一次写这么详细和这么长的博文,可以看出来写到后面的时候已经越来越粗糙了。因为写到后来的时候,自己都已经不知道要写什么了,因为如果再扩展下去,需要增加的东西就太多了。同时也有一部分原因是后面的内容我理解的不是太透彻,同时使用的也很少。总之这会我脑子已经相当混乱了。在这里对那些写博客的大侠们表示深深的敬佩。 

最后要申明的是,这些都是我自己参考视频整理总结出来的,肯定有不专业甚至不对的地方,恳请提出指导,我在学习理解之后,会及时进行修改,谢谢。
开源网格划分软件-Gmsh二次开发教程 (4)网格生成与控制​ ​本章将深入讲解Gmsh的网格生成技术,包括全局/局部网格控制、边界层生成、自适应细化等,并提供完整的代码示例。 阅读详情

相关推荐

Python地理空间数据库之geopandas使用详解

地理空间数据分析在许多领域中都有着广泛的应用,包括地理信息系统(GIS)、城市规划、环境科学、地质勘探等。Python GeoPandas是一个强大的库,旨在简化地理空间数据的处理和分析。本文将深入介绍GeoPandas库,包括其基本概念、功能特性、示例代码以及在实际应用中的应用场景。

Rocky006的博客 1万+

C#调用C动态链接库

学习笔记

qq_28091109的博客 1909

医院网络设计(完整文档+思科拓扑图)

大家好,我是小华学长,一名计算机领域的博主。经过多年的学习和实践,我积累了丰富的计算机知识和经验,在这里我想与大家分享我的学习心得和技巧,帮助你成为更好的程序员。作为一名计算机博主,我一直专注于编程、算法、软件开发等领域,在这些方面积累了大量的经验。我相信分享是一种双赢的方式,通过分享,我可以帮助他人提升技术水平,同时也能够得到学习交流的机会。在我的文章中,你将会看到我对于各种编程语言、开发工具以及常见问题的解析和分析。我会结合自己的实际项目经验,为你提供实用的解决方案和优化技巧。

qq1325513482的博客 2万+

c#中调用其它语言的库总结

c#中调用其它语言的库总结 c/c++: 1.标准c类库 标准c类库是按照C标准规范实现的一个C动态链接库 这种可以使用以下方法进行导入使用: [DllImport("yourDll.dll", EntryPoint = "GetValue")] public static extern bool GetValue(ref byte P1, ref byte P2, ref byte P3); 参数中带指针的: [DllImport("yourDll.dll"] Private static

u012270525的博客 1170

vscode+keil嵌入式软件开发全流程

vscode+keil嵌入式软件开发全流程

AspringQ的博客 6780

GB28181 2022 配置信令

基本参数视频参数选项视频参数属性配置巡航轨迹

ww506772362的专栏 1628

动态链接库 简单的DLL (转载)

动态链接库 智能中国——游戏组  整理编译  

limeng0579的专栏 1437

华为FusionCharge 720kW液冷直流快充桩主电流全路径深度详解

本文档详细介绍了华为FusionCharge 720kW液冷分体式直流充电系统的主电流路径全链路解析,适用于配套DS720-720LCNA1充电主机及DT600L1-CNA1液冷终端、DT250N2-CNA1自然冷终端的运维工作。内容涵盖从电网交流输入到电动汽车充电的全过程,重点解析交流门、整流正门、主控正门等五大柜门区域的核心元器件分布及功能,包括额定参数、安全规范、故障排查等关键运维知识。操作人员需持有高压电工证并通过专项培训,作业时必须严格遵守断电验电、穿戴PPE防护装备等安全红线。文档通过16个关键

2401_84939870的博客 747

【四、静态库与动态库(共享库)】揭开链接库的神秘面纱:手把手教你制作静态链接库与动态链接库

有时候我们对外提供功能的时候,可能不希望对方看到源码,我们就可以制作成库文件,把库文件和头文件给到对方就可以达到提供功能又不暴露源码的目的。链接库就是指将库文件编译后打包为一个二进制文件,这些二进制文件会在程序调用的时候加载到内存中。实际上,一个或多个源文件编译为目标文件后,这个文件中所引用的外部的符号需要通过链接来找到这部分缺失的地址。而根据链接库的链接方式不同,又分为动态链接库和静态链接库。本文将解开静态库与动态库的神秘面纱,手把手教大家制作自己的动态库与静态库。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 3233

单片机毕业设计-基于STM32单片机的智能镜系统-仿真设计

可通过MQ-2监测当前烟雾浓度可通过温湿度传感器监测当前温湿度可通过光照强度传感器监测光照强度可通过蜂鸣器进行烟雾报警可通过语音识别模块进行反馈播报状态可通过按键设置阈值三个继电器控制灯、加湿、风扇标签:STM32单片机、OLED112864、DHT11、BH1750、继电器、SU-03T、MQ-2、蜂鸣器题目扩展:智能家居安防、智能大棚控制系统、智能环境检测系统项目编号:ZL-32-240604-FZ。

bsdog11的博客 966

PCL 平面点云的凹多边形边界提取【2025最新版】

平面点云的凹多边形边界提取及边界轮廓线绘制。博客长期更新,本文最近更新时间为:2025年1月6日。

点云侠的博客 7183

什么是链接库 | 动态库与静态库

静态库、动态库、头文件、库文件详细解析。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 1837

【YOLO系列】YOLOv8详解:模型结构、损失函数、训练方法及代码实现

YOLOv8是Ultralytics团队2023年推出的高效目标检测框架,在速度与精度平衡、多任务支持和易用性方面实现突破。模型采用改进的CSPDarknet主干网络、C2f模块和SPPF加速结构,结合PAN-FPN特征融合和解耦检测头设计,支持目标检测、实例分割和关键点检测任务。创新性地使用CIoU定位损失、Focal Loss置信度损失和动态样本分配策略,显著提升检测性能。实验表明,YOLOv8较前代模型mAP提升5-10%,在TensorRT加速下可达1000FPS,提供5种尺寸灵活选择,成为实时目标

一碗白开水一 2779

windows下动态链接库和静态链接库的介绍

window下有两种库: 1、动态链接库:LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供。(这种方式更灵活,写的程序体积小,但是需要.exe和dll同时发布) 2、静态链接库:LIB包含函数代码本身,在编译时直接将代码加入程序当中(这种方式不是很灵活,因为lib被编译到.exe中,写出的程序体积大,但是只需要发布exe即可,不需要dll

997

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Linux C语言开发 动态链接库以及静态链接库编程简单介绍

差不多可以认为,每个程序都链接到一个或几个库上。任何一个使用了C函数(诸如printf等)都须链接到C运行时库。如果你的程序具有图形界面(GUI),它将被链接到窗口系统的库。如果你的程序使用了数据库,数据库供应商会提供给你一些简化访问数据库的库。在这些情况中,你必须作出选择:静态(statically)还是动态(dynamically)地将程序链接到库上。如果你选择了静态链接,程序体积可能会更大,

wudizuijimo的专栏 3830

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

动态链接库介绍和编程

一,DLL(动态链接库)的介绍:     Microsoft公司自从推出第一个Windows程序以后,DLL就成为了Windows的一部分。DLL不能直接运行,也不能接收入信息,它们可以为其他的应用程序或DLL调用.    Windows API中所有的函数都包含在DLL中,其中有三个最主要的DLL文件:    1,Kernel32.dll:主要用于内存的管理,进程和线程的函数。如:CreateThread();    2,user32.dll:主要用于用户界面。如:MessageBox(); Create

随风飘逸 519

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Windows下动态链接库简单介绍

C/C++ Windows动态链接库简单介绍

qq_47500842的博客 263

libenjoy动态链接库下载介绍

libenjoy动态链接库下载介绍 去发现同类优质开源项目:https://gitcode.com/ 此仓库提供了基于VC6.0编译的libenjoy动态库导出项目的资源文件下载。libenjoy动态库是一款功能丰富的库,能够为开发者提供便捷的开发支持。关于libenjoy的详细信息,您可以通过查阅相关资料来了解更多。 在此,我们简要介绍一下libenjoy动态库: 功能强大:libenjoy动...

gitblog_06795的博客 269

C#调用C++动态链接库方法介绍

下面介绍C#调用C++动态链接库方法。 添加System.Runtime.InteropServices命名空间 如是COM就直接用静态函数调用:

star博客 925

Linux C开发 动态链接库以及静态链接库编程简单介绍

Linux C开发 动态链接库以及静态链接库编程简单介绍 差不多可以认为,每个程序都链接到一个或几个库上。任何一个使用了C函数(诸如printf等)都须链接到C运行时库。如果你的程序具有图形界面(GUI),它将被链接到窗口系统的库。如果你的程序使用了数据库,数据库供应商会提供给你一些简化访问数据库的库。 在这些情况中,你必须作出选择:静态(statically)还是动态(dynamic

Code is to be happy 766

C++中静态链接库与动态链接库的介绍与使用

C++中静态链接库与动态链接库的介绍与使用 一,简介 1.静态库 函数与数据被编译进一个二进制文件(通常扩展名为.lib),在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们 和应用程序的其他模块组合起来创建最终的可执行文件(.EXE),当发布产品时,只需要发布这个可执行文件,并不需要发布使用了的静态库 2.动态库 在使用动态库的时候,往往需要提供两个

liygcheng's coding world - 1816

介绍静态链接库和动态链接库的差别,及在VC++6.0中的建立和使用

首先介绍一下链接库:链接库分为动态链接库和静态链接库两种 LIB是静态链接库,在程序编译连接的时候是静态链接,其相应的文件格式是.lib。即当程序採用静态链接库的时候。.lib文件里的函数被链接到终于的可运行文件里。由于应用程序所需的所有内容都是从库中复制了出来。所以静态库本身并不须要与可运行文件一起发行。 DLL是动态链接库,在程序运行的时候被调用,其相应的文件...

aoe41606的博客 151

MuPDF动态链接库下载仓库介绍

MuPDF动态链接库下载仓库介绍 【下载地址】MuPDF动态链接库下载仓库介绍 MuPDF是一款轻量级PDF阅读器,支持多种文档格式渲染。本仓库提供MuPDF动态链接库资源,方便开发者快速集成PDF阅读功能到应用程序中。由于官方默认生成exe文件和静态库,许多开发者需要动态链接库进行集成。通过本仓库提供的资源,开发者无需...

gitblog_06793的博客 438

动态链接库dll详细的介绍和使用

一、引言 在发行的应用程序中,经常包含动态链接库dll,它包含执行一定功能的函数供其他程序调用。Windows API函数都包含在DLL中,其中有三个最重要的DLL: Kernel32.dll 包含用于管理内存、进程、线程的函数。 User32.dll 包含哪些用于执行用户界面的函数 GDI32.dll 包含哪些用于画图和显示文本的函数 使用动态链接库的好处:

下雨天__的专栏 907
上一篇: c语言连接mysql数据库的实现方法
下一篇: 关于C/C++中typedef的定义与用法总结
流左沙
博客等级 码龄11年 46粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值