动态链接库dll详解

VC++ MFC DLL动态链接库编写详解 虽然能用DLL实现的功能都可以用COM来替代,但DLL的优点确实不少,它更容易创建。本文将讨论如何利用VC MFC来创建不同类型的DLL,以及如何使用他们。一、DLL的不同类型使用VC++可以生成两种类型的DLL:MFC扩展DLL和常规DLL。常规DLL有可以分为动态连接和静态连接。Visual C++还可以生成WIN32 DLL,但不是这里讨论的主要对象。1、MFC扩展DLL每个DLL都有某种类 阅读详情

一、引言

在发行的应用程序中,经常包含动态链接库dll,它包含执行一定功能的函数供其他程序调用。Windows API函数都包含在DLL中,其中有三个最重要的DLL:

Kernel32.dll 包含用于管理内存、进程、线程的函数。

User32.dll 包含哪些用于执行用户界面的函数

GDI32.dll 包含哪些用于画图和显示文本的函数

使用动态链接库的好处:

1.     可以跨语言调用 如你用c语言编写的dll可以被delphi调用

2.     可以作为第三方库提供给其他开发人员,进行二次开发

3.       可以节省磁盘和内存空间 如果多个应用程序调用同一个dll,该dll只放入内存一次,应用进程将dll页面映射到各自的地址空间中。多个进程共享dll的同一份代码,节省内存空间。

二、创建与使用

2.1创建dll

首先打开vs2008,新建项目testDll,选择控制台程序->动态链接库->空项目,然后添加新建源文件dll1.cpp,添加代码

_declspec(dllexport) int add(int a, int b)

{

    returna+b;

}

_declspec(dllexport) int sub(int a, int b)

{

    returna-b;

}

为了让dll导出一些函数,在函数名字前添加一些标识符_declspec(dllexport)。

编译、连接,在Debug下会生成testDll.lib, testDll.exp(用不到) ,testDll.dll.

2.2 Dumpbin工具

为了查看dll中的导出函数,可以利用vs提供的工具dumpbin,目录在…/vc/bin下,该目录下的vcvars32.bat是一个批处理工具,用来建立vc的编译环境,如果dumpbin不能执行,可以先执行下vcvars32.bat。在命令行下输入dumpbin /exports testDll.dll,结果如下


关键看ordinal hint   RVA  name下面的信息,ordinal下的1、2是导出函数的序号,hint是提示码,RVA列出的地址是导出函数在DLL模块中的位置,name是导出函数的名称,这些名称有些奇怪,add的名称是? add@@YAHHH@Z,c++为了支持重载,按照自己的规则修改了函数的名字,称为“名字改编”。

2.3使用dll

动态库有两种引用方式:隐式连接和显式连接。首先我们看隐式连接。

 

新建一测试dll项目testLib,添加代码

extern int add(int,int);

extern intsub(int,int);

int _tmain(int argc, _TCHAR*argv[])

{

int result1 = add(2,5);

int result2 = sub(6,3);

cout<<result1<<"      "<<result2;

}

编译,报以下错误

1>TestLib.obj : error LNK2001: 无法解析的外部符号"int __cdeclsub(int,int)" (?sub@@YAHHH@Z)

1>TestLib.obj : error LNK2001: 无法解析的外部符号"int__cdecl add(int,int)" (?add@@YAHHH@Z)

这是调用库函数经常见到的错误,原因是没有找到函数的实现。

我们把testDll.lib,testDll.dll拷贝到测试程序的目录下,然后选中工程名右击选择属性,在弹出的对话框选择链接器->输入,添加testDll.lib,重新编译,没问题了。

除了使用extern声明引用外部函数外,还可以使用标识符_declspec(dllimport)表明函数是从dll导入的。下面我们修改一下导入函数的声明,如下

_declspec(dllimport) int add(int,int);

_declspec(dllimport)int sub(int,int);

一般来说,客户程序并不知道函数的原型,所以我们在发布动态库时,除了提供*.dll和*.lib文件,还应提供导出函数声明的头文件*.h。为此,我们在动态库的工程中添加头文件dll1.h供库程序和客户程序使用,定义一个宏区分是导入还是导出函数,dll1.h头文件代码如下

#ifdef DLL1_API

#else

    #define DLL1_API_declspec(dllimport)

#endif

DLL1_API int add(int,int);

DLL1_API intsub(int,int);

然后再dll1.cpp中添加宏定义和引用头文件,

#define DLL1_API _declspec(dllexport)

#include "dll1.h"

把testDll1.lib,testDll1.dll和dll1.h拷贝到测试程序的目录下,添加引用头文件,编译运行。好了,到此动态库的基本使用已经完成了。

2.4如何从dll中导出类

我们在dll1.h中添加以下代码:

class DLL1_API Point

{

public:

   voidoutput(int a, inty);

};

在dll1.cpp中实现output函数

void Point::output(int x, int y)

{

   std::cout<<x<<"    "<<y;

}

在testlib工程中添加测试代码:

   Point p;

   p.output(1,1);

编译运行。

我们使用dumpbin工具查看dll导出函数,如下, dll导出了一个类Point,还导出了类的成员函数output。

 

2.5 extern ”C” 的使用

我们还记得查看导出的函数名字进行了改编,如果用C语言调用c++编写的dll,将找不到导出函数。我们希望动态链接库文件在编译时,导出函数的名字不要发生改编,这时需要在定义导出函数时添加限定符extern ”C”.下面我们对库程序进行修改,对Point的有关代码注释,代码如下:

dll1.h如下

#ifdef DLL1_API

#else

   #define DLL1_APIextern "C" _declspec(dllimport)

#endif

DLL1_API int add(int,int);

DLL1_API int sub(int,int);

dll1.cpp如下

#define DLL1_API extern "C" _declspec(dllexport)

#include "dll1.h"

#include <iostream>

int add(int a, int b)

{

   returna+b;

}

 

int sub(int a, int b)

{

   returna-b;

}

使用dumpbin工具查看导出函数如下,可以看出导出函数名字没有发生改编。


利用extern "C"可以解决c语言和c++之间的相互调用时的函数命名问题,但是不能用于导出一个类的成员函数,只能用于导出全局函数,所以我们注释了Point类。

但是,如果我们改变了调用约定,即使加上了限定符extern "C",函数的名字也会发生改变。

调用约定主要规定了一个函数被调用时参数的入栈方向和调用者还是被调用者清除栈。主要的调用方式有_cdcel,_stdcall,fastcall,thiscall,nakedcall.C/C++语言函数的默认调用方式是_cdcel,_stdcall是PASCAL程序的缺省调用方式, windows的API函数也是这种方式,我们将常看到函数名称前有WINAPI修饰。

在dll库的函数声明和定义中都加上_stdcall调用约定,重新编译程序。然后使用dumpbin工具查看导出函数名字,可以看到add函数的名字为_add@8,函数名字前加了一下划线,后面加了@和数字8,表示参数所占的字节数。


2.6 使用模块定时文件导出

我们知道,C语言和Delphi的调用约定是不同的,如果我们用C语言编写一个dll,用delphi调用,在导出函数中应指定标准调用约定_stdcall,但仍会出现问题,因为函数名字会发生改变。解决方法是通过一个称为模块定义文件(def)的方式解决名字改编问题。

我们再建一个项目dll2,为该项目添加一个源文件dll2.cpp,代码如下

int _stdcall add(int a, int b)

{

   returna+b;

}

然后添加一个模块定义文件dll2.def,代码如下

LIBRARY  "dll2"

EXPORTS

add

其中LIBRARY语句制订动态链接库的名称,该名称与生成的动态链接库的名称一定要匹配,EXPORTS语句表明DLL将要导出的函数,以及为这些导出函数指定的符号名。编译dll2,然后用dumpbin工具查看导出函数名,如下


可见,导出函数名是按def文件指定输出的,没有发生名字改编。

2.7 显式加载dll

基本函数:

HMODULE LoadLibrary(LPCTSTR lpFileName);

FARPROC GetProcAddress(HMODULE hModule,LPCSTRlpProcName);

在测试程序中添加

   HMODULE h = LoadLibrary("dll2.dll");

   typedefint (*Fun)(int,int);

   Fun f = (Fun)GetProcAddress(h,"add");

   if(!f)

      return-1;

   int d = f(3,6);

   FreeLibrary(h);

输出结果d=9.

动态加载在需要时才加载DLL,而隐式连接方式实现比较简单,配置好,可以随时调用DLL导出的函数。

在dll2.cpp中函数前加上调用约定_stdcall,编译后的dll2.dll拷贝至测试程序下,发现测试程序不能正确执行,必须声明函数指针时也加上调用约定。

当DLL中的导出函数采用的是标准调用约定时,访问该DLL的客户端程序也应该采用该类型类访问相应的导出函数。

2.8

如果到处函数发生名字改编,动态加载DLL会发生什么问题?

我们修改第一个项目dll1的导出函数,不加extern”C”和_stdcall,add导出函数名字为?add@@YAHHH@Z,然后调用该函数发现找不到该函数。

为了验证?add@@YAHHH@Z就是add的名字,修改获取地址的那行代码,

   Funf = (Fun)GetProcAddress(h,"?add@@YAHHH@Z");

发现正确运行。

除了使用导出函数的名称外,还可以使用导出函数的序号来访问该函数,使用MAKEINTERSOURCE宏把指定的函数序号转化为指定的函数名字字符串。修改如下

   Funf = (Fun)GetProcAddress(h,MAKEINTRESOURCE(1));

发现能正确输出。

2.9 注意

像extern "C", _declspec(dllexport),_declspec(dllimport)标志符可以只在函数声明的时候指定,在实现时可以不加,但是调用约定_stdcall必须在声明和实现时都加上,否则编译器认为是不同的函数,出现重定义错误,使用显式调用时函数指针也要加上_stdcall。


【DLL】C++动态链接库DLL的创建与使用详解 本文详细介绍了DLL(动态链接库)的创建、使用、调试及最佳实践。 阅读详情

相关推荐

VC++调用MATLAB生成的DLL动态链接库详解

在现代工程开发中,MATLAB凭借其强大的数值计算能力、丰富的工具箱以及高效的算法开发环境,广泛应用于信号处理、图像识别、控制系统等领域。而VC++作为系统级开发语言,具有高效的执行性能和底层硬件控制能力。将MATLAB的M文件编译为DLL并在VC++中调用,能够有效融合两者优势,实现算法开发效率与系统执行性能的双重提升。本章将介绍MATLAB与VC++集成调用的基本原理,重点分析为何选择将M文件封装为DLL进行调用,并简要说明整个集成调用的技术流程框架,为后续章节的操作实践与性能优化打下坚实基础。

weixin_30820933的博客 1191

dll动态链接库使用

C#调用dll,复制dll到exe同目录下,通过DllImport引入dll到程序中,具体操作:1)引用命名空间:using System.Runtime.InteropServices;2)在C#语言源程序中声明外部方法:[DllImport("dll名称+后缀")]//如:[DllImport("user32.dll")]static extern int Message...

weixin_34161029的博客 185

Matlab TreeBagger实战:用随机森林预测房价的5个关键步骤(附完整代码)

本文详细介绍了使用Matlab的TreeBagger工具包构建随机森林模型预测房价的完整流程。通过波士顿房价数据集实战,涵盖数据预处理、模型构建、参数调优、特征重要性分析及高级应用(如分位数回归)等5个关键步骤,并附有完整代码,帮助读者快速掌握这一强大的回归分析工具。

ol789012的博客 444

C++学习笔记~动态库生成中的dllimport、dllexport与(.def)文件

以下是关于C++动态库生成中dllimport、dllexport与(.def)文件的博客,通过阅读可以较好地理解它们的作用和区别。 1.https://www.cnblogs.com/de0319gh/p/3254013.htmldllimport与dllexport作用与区别 这篇博客中给出了C++导出动态库时,是否需要dllimport的情况以及必须具备的原因。 以下为博客全文: ...

zlibo丶的博客 3311

深度强化学习研究笔记(1)——入门(马尔科夫决策过程,贝尔曼方程,价值迭代和策略迭代)

1. 强化学习(Reinforcement learning)概述 强化学习(Reinforcement learning)的基本内涵是将问题用代理和环境进行建模。其中代理能够对环境执行一些特定的动作a∈Aa \in Aa∈A,从而到达某个状态s∈Ss \in Ss∈S,然后我们就可以根据该状态为代理赋予特定的奖励rrr。强化学习的基本思想如下图所示: 代理的目标是最大化未来的奖励总和,它通过将...

越野者的博客 5280

东方通TongWeb虚拟主机配置全流程:从创建到应用部署的保姆级教程

本文提供东方通TongWeb虚拟主机从创建、HTTP通道配置到应用部署的完整实战指南。重点解析虚拟主机的逻辑隔离价值、通道参数调优原理及企业级多应用部署架构,并涵盖常见报错排查与性能优化建议,旨在帮助运维和开发人员高效、稳定地完成应用系统部署。

oil88的博客 530

DLLImport:C#引用第三方DLL动态链接库

最近一个项目,使用到第三方公司提供的算法模型,不会引用,这里让他们程序员写了一个demo,能使用,这里就简单写一下。 新建类LiXue,先需要添加引用 using System.Runtime.InteropServices; 动态链接库调用:“[DllImport(@"D:\LandGZ_ShangTi.dll", CharSet = CharSet.Auto, CallingConv...

qq_41306610的博客 4111

MQTT阿里云OTA 调试记录

2.验证,这个验证是什么意思呢,就是阿里云会把你包的信息,比如包大小,streamid(相当于包的识别码),版本号发送给你的设备,然后如果你没发送升级成功的包给阿里云,这里会是一直验证中的状态,那你的设备每次重新连接阿里云,发送connect包给阿里云的时候,阿里云就会发送一次这个验证(upgrade)包。提取到了之后就可以发送请求包了,这个请求包比较坑,也可能是我没付费,他的包一次最多只有1024个字节的数据。之前说了,验证状态下,设备发送connect包给阿里云,阿里云就会发一个upgrade包给你。

qq_42585211的博客 1231

动态链接库DLL基础知识

一个感觉就是乱!

两水先木示的博客 2386

ANSYS MAXWELL内置式永磁同步电机(IPMSM)转矩最大时输入电流相位的确定

1.在转子转速为零时看一个周期内的转矩变化

qq_41752507的博客 6516

thermal系列(5)-DTSI中配置Thermal

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.youkuaiyun.com/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录thermal系列目录DTSI中配置ThermalDTSI节点类型描述CPU0的配置举例CPU核hot-plugging举例修改热缓解阈值DTSI的node中带有tracks-lowDTSI中关闭某个Thermal Zones thermal系列目录 thermal系列(1)-引言部分 thermal.

fulinux的博客 1230

动态链接库文件DLL详解

一、动态链接库的概念  动态链接库(Dynamic Link Library,缩写为DLL)是一个可以被其它应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源。动态链接库文件的扩展名一般是dll,也有可能是drv、sys和fon,它和可执行文件(exe)非常类似,区别在于DLL中虽然包含了可执行代码却不能单独执行,而应由Windows应用程序直接或间接调用。  动态链接是相对于静态链

大方的专栏 1878

【Bluetooth蓝牙开发】一、开篇词 | 打造全网最详细的Bluetooth开发教程

1、开篇词 2、蓝牙开发入门 3、蓝牙协议栈总览 4、蓝牙协议栈——物理层 5、蓝牙协议栈——链路层 6、蓝牙协议栈——传输层 7、蓝牙协议栈——L2CAP协议 8、蓝牙协议栈——ATT协议 9、蓝牙协议栈——GATT协议 10、蓝牙通信流程分析 11、蓝牙协议栈——Bluez交叉编译 12、蓝牙调试工具汇总

Donge's Blog 1万+

C/C++动态链接库(DLL)详解

整理了动态链接库笔记,供大家参考。欢迎大家留言讨论。 1. 动态链接库(dll)简介 2. 动态库和静态库区别 3. 使用动态链接库(dll)的好处 4. 内存页面 5. 动态链接库被多个进程访问 6. 动态链接库加载的两种方式 7. 如何查看动态链接库(dll)导出哪些函数 8. 创建动态链接库(dll) 9. 使用动态链接库(dll) 来源:孙鑫_VC++_学习笔记 ...

独步天秤的博客 9484

ABAP Secure Storage 在事务码 SM59 中的应用

系统管理人员在进行维护时,应关注相关日志信息,及时发现可能出现的安全异常,并针对不同安全等级的操作制定相应的备份与恢复策略,以降低潜在风险。该区域在设计上具备高度隔离性,仅允许经过授权的组件访问。保存后,系统会将密码存储在 Secure Storage 中,这种处理方式充分体现了 SAP 标准程序在安全设计上的考量。对于系统管理员而言,这种机制在日常维护与审计中提供了有力的支持,可以通过比对存储数据的哈希值或其他完整性校验手段,及时发现异常变动,保障系统长期稳定运行。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 669

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

windows中dll和linux中so的动态链接库的详解

1 生成windows中静态链接的静态库

Jack.Tech_StoreRoom 7491

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

探索动态链接库的奥秘:dll_demo项目详解

探索动态链接库的奥秘:dll_demo项目详解 项目介绍 在现代软件开发中,动态链接库(Dynamic Link Library,简称DLL)扮演着至关重要的角色。它们不仅提高了代码的复用性,还优化了系统的资源管理。dll_demo项目正是为了帮助开发者深入理解DLL的创建与使用而设计的。通过这个项目,你将掌握如何从头开始创建一个DLL,并将其集成到你的应用程序中。无论你是初学者还是有经验的开发者...

gitblog_00929的博客 507

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

windows DLL技术-动态链接库(DLL)详解

本文介绍了在VS2019中创建和使用动态链接库(DLL)的方法。DLL是一种可在运行时被多个程序共享的代码模块,具有节省内存、便于更新等优势。文章详细讲解了两种创建DLL项目的方式,分析了关键的头文件定义(使用__declspec(dllexport/dllimport)修饰符)和源文件实现,包括导出C风格函数、C++类和变量。最后说明了可选的DLL入口点函数DllMain的实现及其调用时机。通过示例代码展示了完整的DLL开发流程,为模块化开发和代码复用提供了实践指导。

王马的博客 501

C/C++ DLL 动态链接库的开发与示例详解

本文详解 DLL 动态链接库的开发流程,包含完整开发示例,介绍如何创建、调用及调试 DLL 文件,适用于 Windows 平台下的 C/C++ 开发者提升代码复用与模块化设计能力。

技术那些事 881

为什么动态链接.dll和.lib都需要(详解静、动态链接库)

最近接触到的游戏会有很多的dll和lib文件,之前关于动态链接库和静态链接库一直很不理解,最近发现了一篇很好的文章,非常清晰的讲解了dll与lib的关系,这里拿出来给大家分享下。 原文链接:http://blog.163.com/zhengjiu_520/blog/static/3559830620093583438464/   前面有一章说编译与链接的,说得很简略,其实应该放到这一章一块儿来说的...

weixin_43744293的博客 9461

动态链接库dll详解【转】

转自http://blog.youkuaiyun.com/skilledprogrammer/article/details/7032494 一、引言 在发行的应用程序中,经常包含动态链接库dll,它包含执行一定功能的函数供其他程序调用。Windows API函数都包含在DLL中,其中有三个最重要的DLL: Kernel32.dll 包含用于管理内存、进程、线程的函数。 User32.

明月清风 精进不止 703

什么是动态链接库DLL?以及DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)

一、DLL的概念 DLL(Dynamic Link Library),动态链接库文件,又称“应用程序拓展”,是软件文件类型,扩展名是“.dll”。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。例如:kernel32.dll中含有LoadLibrary(...

weixin_36711901的博客 2245
上一篇: c/c++经典书籍
下一篇: windows下c++编写多线程
skilledprogrammer
博客等级 码龄19年 78粉丝 53原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值