孙鑫VC学习笔记:第十九讲 动态链接库

孙鑫视频VC++深入详解学习笔记 <br />VC++深入详解学习笔记<br />Lesson1: Windows程序运行原理及程序编写流程<br />Lesson2: 掌握C++基本语法<br />Lesson3: MFC框架程序剖析<br />Lesson4: 简单绘图<br />Lesson5: 文本编程<br />Lesson6: 菜单编程<br />Lesson7: 对话框编程<br />Lesson9: 定制应用程序的外观<br />Lesson10: 绘图控制<br />Lesson11 图形的保存和重绘<br />Lesso 阅读详情
动态链接库
Windows API中的所有函数都包含在DLL中。其中有三个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。
---------------------------------------------------------------------------------
静态库和动态库
静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件);
在使用动态库的时候,往往提供两个文件:一个因入库和一个DLL。因入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行时候,再去加载DLL,访问DLL中导出的函数。
---------------------------------------------------------------------------------
 
使用动态链接库的好处
可以采用多种编程语言来编写。
增强产品的功能。
提供二次开发的平台。
简化项目管理
可以节省磁盘空间和内存。
有助于资源的共享。
有助于实现应用程序的本地化
---------------------------------------------------------------------------------
动态链接库被多个进程访问:
---------------------------------------------------------------------------------
动态链接库的加载方式:1.隐式加载 和 2.显示加载
 
一、先做一个隐式加载的例子:
      1)用MFC向导新建一个Win32 Dynamic-Link Library的工程项目,名字叫做Dll1,
并且新建一个Dll1的C++源文件
      2)在Dll1.cpp文件中,编写完成加法与减法运算的函数add()和substract()
      3)编译之后,我们可以在工程目录的Debug文件夹中发现一个Dll1.dll的文件,
这就是动态链接库文件。
 
现在已经有了一个动态链接库,那么怎么让其他程序访问它呢?
     首先,动态链接库中的文件必须被导出后才能被其它程序访问。
我们可以用VC自带的工具Dumpbin来查看那些动态链接库的函数被导出了。
可在命令行下进入Debug所在目录,输入以下命令
dumpbin -exports dll.dll 
有些时候由于某种安装原因,dumpbin被认为是无效命令,可以到VC的安装目录
../Microsoft Visual Studio/VC98/Bin/下
找到VCVARS32.bat并在命令行运行,之后就能执行dumpbin命令了。
输入dumpbin -exports Dll1.dll 就可以查看函数的导出状况了,
不过我们没有看到任何导出的函数。
怎样才能让我们自己编写的函数被导出呢?
只要在每个函数定义的前面加上_declspec(dllexport)标记就行了,如下所示:
 
_declspec(dllexport) int Add(int x,int y)
{
return x+y;
}
_declspec(dllexport) int Subtract(int x,int y)
{
return x-y;
}
加了_declspec(dllexport)以后再编译一下,就会再生一个*.lib引入库文件和一个*.exp文件,里面包含的是导出的函数或者变量的符号名。而exp文件是一个输出库文件。
这时我们再一次在命令提示符下面输入命令:dumpbin -exports Dll1.dll
就会有下面的结果出现
 
 
   然后,新建一个基于对话框的MFC AppWizard 测试工程,在对话框上添加Add与SubTract按钮,
在这两个按钮中,分别调用动态链接库中所写的两个函数。
不过为了使编译器认识动态链接库的Add,Subtract,必须在之前使用两个声明:
extern int Add(int x,int y);
extern int Subtract(int x,int y);
 
接下来就可以在两个按钮中调用动态链接库的函数了,代码如下:
void CDllTestDlg::OnBtnAdd()
{
CString str;
str.Format("3+5=&d",Add(3,5));
MessageBox(str);
}
 
void CDllTestDlg::OnBtnSubtract()
{
CString str;
str.Format("5-3=%d",Subtract(5,3));
MessageBox(str);
}
 
 注意:在编译之前需要将前面编译好的Dll1.dll和Dll1.lib拷贝到DllTest项目目录下,
同时按下F7,在工程设置中的Link选项卡的Object/library modules中
(在project--->setting--->link--->Object/Library Modules)填写Dll1.lib,
否则虽然声明了动态链接库的两个函数,在编译的时候不会出错,
但是在链接的时候会找不到这两个函数,从而报错。
 
如果要查看DllTest.exe文件信息,使用命令行dumpbin -imports dlltest.exe
 
    上面说过,在调用动态链接库的两个函数之前,应该事先用extern声明一下,
其实也可以用_declspec(dllimport)标识符声明,所以我们可以用
_declspec(dllimport) int Add(int x,int y);
_declspec(dllimport) int Subtract(int x,int y);
取代
extern int Add(int x,int y);
extern int Subtract(int x,int y);
而且用这种方法有个好处,_declspec(dllimport)会告诉编译器要引用的函数是从*.lib文件中输入的,
这可以让编译器生成效率更高的代码。
---------------------------------------------------------------------------------
二、我们在编写动态链接库的时候,往往会提供一个包含导出函数的原型声明的头文件,
     可以将这个头文件提供给其他使用动态链接库的开发人员,
     他们就可以通过这个头文件获得导出函数的信息以及相关的说明文档。
     下面在动态链接库工程中添加一个这样的头文件,步骤如下:
    1)增加一个Dll1.h的头文件
    2)事实上,这个头文件是提供给客户端使用的,所以我们把声明动态链接库两个函数的任务放到这里
_declspec(dllimport) int Add(int x,int y);
_declspec(dllimport) int Subtract(int x,int y);
这样,我们只要在DllTest工程中#include这个头文件,就声明了动态链接库的两个函数。
    3)可以对这个头文件改进一下,让它既可以为客户端使用,也可以为动态链接库本身服务。
首先在Dll1.h中添加一个条件编译指令,代码如下:
 
在Dll.cpp文件,首先定义一个宏,#define DLL_API _declspec(dllexport)
然后包含这个头文件:#include "Dll.h"
接着去掉函数定义前的_declspec(dllexport)标识符,
(为什么可以去掉这个标识符,而不影响函数的导出?大家自己想想吧。)
代码如下:
 
这样做是为了方便外部程序调用同时方便内部程序使用,因为动态链接库中只有导出的函数才可以被使用,没有导出的函数在外部是看不到的,是不能被访问的
 
    4)接下来导出整个类,代码:
注意:在客户端对类成员函数的访问,仍然受制于访问权限
定义类的时候在Class 与 point之间加了DLL_API就会导出整个类。
类的实现:
    接下来我们在测试工程中新建一个按钮,调用动态链接库函数,代码如下:
---------------------------------------------------------------------------------
三、我们自己编写的到这里已经可以在C++程序中正常运行了,但是如果把这个动态链接库拿给其他语言用,比如拿给C语言调用,又会出问题,问题就在于C++导出或导入动态链接库会发生名字的改编,
在C语言中导入动态链接库时,不会正确地将名字改编回来,于是会找不到函数。
那么有没有办法使编译的时候不发生名字改编呢?
只要在定义DLL_API宏的时候,加上一句extern "C" (C要大写)就行了,如下:
#define DLL_API extern "c" _declspec(dllexport)
这样编译器就不会进行名字改编,导出的函数跟我们自己写的一模一样,
一个用C语言编写的客户端程序就可以调用这个用C++编写的动态链接库。
 
注意:用extern "c"不让名字发生改编有两个缺点是,
一是不能导出类中的函数,只能导出全局函数;
二是如果函数使用标准调用约定_stdcall,即使用了extern "c",函数仍会发生改编。
---------------------------------------------------------------------------------
四、上面的方法可以实现编译时不发生名字改编,但是有两个缺点,特别是使用_stdcall时,
     仍然会发生名字改编。下面介绍一种模块定义文件的方式来解决这个问题:
 
   1)接下来新建一个动态链接库文件,文件名为Dll2.cpp文件代码为:
    2)新建一个模块文件Dll.def(可以先新建一个文本文档,然后将它改成Dll2.def,
注意连扩展名也要改),将其加入要项目工程当中。
    3)在VC编辑器中对Dll2.def进行编辑,添加代码
LIBRARY Dll2:指定动态链接库的内部名称,这句不是必须的
EXPORTS :即使调用_stdcall约定,也不会发生改编,而只会调用这里显示的
Add与Subtract:字符串
 
EXPORTS 语句引入了一个由一个或多个 definitions(导出的函数或数据)组成的节。每个定义必须在单独一行上。EXPORTS 关键字可以在第一个定义所在的同一行上或在前一行上。
*.def 文件可以包含一个或多个 EXPORTS 语句。
    4)下面在DllTest工程中显式地加载这个动态链接库,并且测试一下Dll2。
动态加载动态链接库要用到LoadLibrary函数;
接下来在MFC文件中改写按钮void CDllTestDlg::OnBtnAdd() 代码:
 
 注意:1.因为调用LoadLibrary时动态加载动态链接库,所以不需要头文件和.lib文件
2.如果我们在动态链接库中使用标准调用约定_stdcall来导出函数,在模块定义文件方式下,导出的函数名字不会发生改编。但是在客户端的可执行程序中,定义函数指针类型时也要采用_stdcall调用约定:typedef int (_stdcall* ADDPROC)(int a , int b );
3.动态调用动态链接库时,最好不要发生名字改编,不然函数名字发生改编之后我们不知道函数名字就无法根据函数的名字进行调用了。当然如果知道DLL中函数的序号,这时可以使用宏MAKEINTRESOURCE把序号转变成名字,如:
ADDPROC Add=(ADDPROC)GetProcAddress( hInst,MAKEINTRESOURCE (1));

DllMain
它是一个动态链接库的可选入口点。
The DllMain function is an optional entry point into a dynamic-link library (DLL). If the function is used, it is called by the system when processes and threads are initialized and terminated, or upon calls to the LoadLibrary and FreeLibrary functions.
 
DllMain is a placeholder for the library-defined function name. You must specify the actual name you use when you build your DLL. For more information, see the documentation included with your development tools.
 
 
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
);
 
当我们的动态链接库不再使用时可以调用FreeLibrary使动态链接库使用计数减1,当使用计数为零时,系统会收回模块资源
FreeLibrary
The FreeLibrary function decrements the reference count of the loaded dynamic-link library (DLL). When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid.
 
BOOL FreeLibrary(
HMODULE hModule
);
 
基于FaceX-Zoo实现的Face Mask Adding人脸戴口罩 人脸系列文章目录 文章目录人脸系列文章目录前言一、加口罩效果二、实现原理二、代码实现 前言 目前人脸加口罩均为在人脸位置贴图式的,非常不真实。前段时间京东开源一个基于PRnet实现的3D口罩拟合人脸,加口罩非常逼真,但是只是单独一个加口罩demo,没有完整的流程。于是本人结合人脸检测,关键点对齐。PRnet加口罩实现一个完整的加口罩流程。只需一个命令简单方便调用,实现人脸加口罩。 https://github.com/JDAI-CV/FaceX-Zoo 一、加口罩效果 下图可以看出效果还是非常逼真的 阅读详情

相关推荐

薄膜电容寿命预测全解析:从理论到实践,5步搞定可靠性评估

本文全面解析薄膜电容寿命预测的理论与实践,提供五步可靠性评估流程,涵盖温度应力、电压应力等关键因素分析,并分享提升寿命的实用技巧。特别适用于新能源、电动汽车等领域的设计工程师,帮助准确预测薄膜电容在实际工况下的使用寿命。

weixin_33712987的博客 432

孙鑫 VC++深入详解第19课——动态链接库

1.动态链接库的编码过程 ①首先明确了在编译的时候,只编译C和CPP文件,然后根据include打开相应的.h文件 ② 在相应的C或者CPP文件中加入 #define TFFT_API extern "C" _declspec(dllexport) ③在相应的头文件.h中加入: #ifdef TFFT_API #else #define TFFT_API extern "C" _

人的梦想是不会终结的 1397

基于TMS320F28034的SCI技术简介

28034的SCI没有接入DMA总线,不过它的收发都有4级的FIFO,在一定程度上也能够缓解cpu的压力。 本文的设计思想如下: 接收:通过中断的方式,4级FIFO满后在中断里将RXDATA出栈。不过就存在这种情况,发送端发出的数据未必能填满4级FIFO,然而此时配置的是4级FIFO触发中断,所以这种情况下中断无法及时地触发。怎么办? 本文的做法是在主程序下循环读取FIFO。这样就可以确保在数据高速传输时,通过中断和主程序及时和有效地接收到总线的数据。(不过当总线波特率较低时可能中断是几...

weixin_48388779的博客 1406

动态库(非MFC动态库)

一、C语言动态库   1、创建C语言动态库,并封装函数:     1)创建新工程:Win32 Dynamic-Link Library            2)添加SourceFiles文件:Cdll.c              Cdll.c中的内容:       //创建C的动态库 //_declspec(dllexport)声明导出 _declspec(dllex...

weixin_30904593的博客 183

Halcon阈值算子 -- 局部阈值之dyn_threshold

Halcon阈值算子 – dyn_threshold HALCON有很多阈值算子,接下来将一一介绍。本文先介绍dyn_threshold。 以下介绍主要参考HALCON帮助文档,并加上自己的体会。如有纰漏,欢迎留言指出 理论介绍 dyn_threshold算子的函数签名如下: dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset, LightDark : ) 输入参数有: OrigImage:待处理图像 ThresholdIm

m0_47015717的博客 5385

IC617多线程仿真卡死?手把手教你用TigerVNC替换解决ADE XL Explorer问题(附Manjaro/Centos8实测)

本文针对IC617在Manjaro、CentOS 8等高版本Linux系统中运行ADE XL Explorer进行多线程仿真时出现的卡死问题,提供了详细的诊断与解决方案。文章指出问题根源在于软件内置的旧版VNC组件不兼容,并手把手指导用户通过使用TigerVNC替换原组件来彻底解决,附有在Manjaro和CentOS 8系统上的实测步骤与验证方法。

hill8的博客 774

孙鑫-MFC笔记十一--动态链接库

Windows三个重要的动态链接库 Kernel32.dll,它包含用于管理内存、进程和线程的各个函数; User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数; GDI32.dll,它包含用于画图和显示文本的各个函数。 静态库和动态库区别: 静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时

工作笔记 6621

CAN总线BusOff恢复机制详解:快慢恢复策略在车载网络中的实战应用

本文深入解析了CAN总线BusOff恢复机制,重点阐述了快慢恢复策略在车载网络中的工程应用。通过对比NXP S32K与STM32平台的实现代码,并结合CANoe仿真与参数优化方法,为工程师提供了从理论到实战的完整解决方案,旨在提升车载网络的可靠性与功能安全。

7up55的博客 615

孙鑫:第十九讲 动态链接库

动态链接库     Windows API中的所有函数都包含在DLL中。其中有三个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。 静态库和动态库 静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。

dlfer11的专栏 836

ncode控件使用总结

数据格式txt转s3t #HEADER #TITLES Absolute_Time,COG_Ax,COG_Ay,COG_Az,LF_SPINDLE_AZ #UNITS ,g,g,g,g, #DATATYPES Double,Float,Float,Float,Float #DATA 2. 导入s3t数据 3. 输入数据控件 直接拖入数据源或者添加控件数据 4.

技术联盟 2006

利用 SAP Joule 提升 ABAP 开发效率的前提条件与限制全解析

综上,想要在 ABAP Development Tools 中顺利使用 SAP Joule,既要准备好 BTP、IAS、ABAP 系统与 ADT 的版本与信任链,也要理解许可证、配额、语法范围等限制。只有在这些前提全部满足后,Joule 才能真正发挥生成式 AI 的价值,帮助 ABAP 开发者从繁琐模板中解放出来,把注意力投入在业务创新与 Clean Core 改造之上。未来 SAP 还将扩展中文语境、自动修复建议以及跨系统智能代理等功能,值得持续关注。

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

孙鑫VC++视频教程笔记

写在前面的话:在学习孙鑫老师的VC++视频时,为了加深自己对知识的深入理解,就做了下面的笔记。 第一讲: 第二讲: 第三讲: 第四讲: 第五讲: 第六讲: 第七讲: 第八讲: 第九讲: 第十讲: 第十一讲: 第十二讲: 第十三讲: 第十四讲: 第十五讲: 第十六讲: 第十七讲: 第十八讲: 第十九讲:动态链接库 第二十讲: 转载于:https://www.c...

weixin_30861797的博客 120

[27] cuda 应用之 核函数实现图像通道变换

[27] cuda 应用之 核函数实现图像通道变换

yohnyang的博客 201

孙鑫VC++视频教学19笔记之动态链接库创建

背景           由于项目需要用到delphi写的客户端来调用dll,并通过dll与Qt写的项目进行socket通信。dll使用C++来写的,这也让我有压力再去回顾一下孙鑫老师的VC++教学视频。主要看的19课的动态链接库 静态链接库 http://blog.youkuaiyun.com/ziren235/article/details/1381916 静态链接库是以lib作为后缀的 动

chenbaohai的专栏 3952

efm32 入门.pdf

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

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

孙鑫VC学习笔记:第二十讲 Hook编程

 通过安装Hook过程,可以用来屏蔽消息队列中某些消息The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain ty

遐迩思的专栏 4896

孙鑫VC课程-动态链接库学习笔记

动态链接库学习笔记一.使用dumpbin在命令窗体查看dll信息1.1查看dll的导出函数当前工程目录下/debug/dumpbin -exports XXX.dll1.2查看可执行程序用到的动态库,以及相关的函数信息    1.2.1当前工程目录下/debug/dumpbin -imports XXX.exe    1.2.2使用工具depends查看二.编写Wi

chm_study的专栏 749

孙鑫VC学习笔记:第二十讲 (一) Hook编程

通过安装Hook过程,可以用来屏蔽消息队列中某些消息The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types o

梦想---软件设计师 1801

孙鑫 VC++ 视频教程--初学者值得一看

孙鑫C++视频教程 rmvb格式 全20CD完整版,初学者值得一看, 20CD完整版的下载如下: (注意以下为FTP下载地址,建议使用迅雷等下载工具下载,全20CD,已添加完整) 迅雷专用高速下载 孙鑫C++教程(全20讲)PPT讲义.rar 迅雷专用高速下载 孙鑫C++教程01.rar 迅雷专用高速下载 孙鑫C++教程02.rar 迅雷专用高速下载 孙鑫C++教程03.rar 迅雷专用高速下载 孙鑫C++教程04.rar 迅雷专用高速下载 孙鑫C++教程05.rar 迅雷专用高速下载 孙鑫C++教程06.

社福之路——专栏 1373

孙鑫C++视频教程 rmvb格式 全20CD完整版 精品分享

http://club.topsage.com/thread-156290-1-1.html 孙鑫C++视频教程 rmvb格式 全20CD完整版 精品分享 [复制链接] 3Cccc 38 主题 473 帖子 1348 金币 ...

weixin_33850015的博客 755

Windows程序设计__孙鑫C++Lesson19《动态链接库》

Windows程序设计__孙鑫C++Lesson19《动态链接库》 本节要点: 1.动态链接库与静态链接库 2.查看动态链接库中导出函数和程序中导入函数 3.动态链接库加载的的隐式连接 4.动态链接库函数的外部提供 5.动态链接库导出函数的名字改编 6.整个类的导出及类的部分函数的导出 7.动态链接库的显式加载和卸载 8.利用MFC AppWizard(dll)新建Dll工程

王定桥的专栏 2333

职业写作者的机械键盘选型指南:准、稳、省力才是生产力核心

机械键盘作为专业文字工作者的核心输入设备,其本质是服务于高频、高精度、长时间手指运动的人体工学工具。它并非游戏外设的延伸,而是基于触发行程一致性、回弹曲线线性度、键帽摩擦系数等生物力学参数构建的精密交互系统。技术价值体现在降低无效疲劳、减少腱鞘炎风险、提升思维输出效率;典型应用场景覆盖法律文书撰写、技术文档编写、学术写作及新媒体内容生产等对准确率与持续性要求严苛的领域。本文聚焦‘机械键盘’与‘职业写作者’两大热词,解析如何从轴体物理特性、PCB信号路径、定位板材质到固件调校,构建真正可持续的码字生产力系统。

weixin_33834910的博客 278

孙鑫 第十九课 动态链接库DLL

关于DLL的调用方式有两种①静态调用方式 在制作DLL时使用_declspec(dllexport)声明函数为导出函数,编译成功后会在Debug下生成.dll 和 .lib文件,其中.lib文件存储的是DLL中函数的符号信息。 .dll文件中存储的是函数的具体实现。静态调用方式下只需要在.exe引入.lib文件,而.dll文件要在程序可以搜索到的路径下。 eg.//制作Dll,Dll.cpp_de

cuihao0532的博客 669

孙鑫教学视频笔记(19)动态链接库

动态链接库Windows API中的所有函数都包含在DLL中。其中有三个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。静态库和动态库静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下

peng6662001的专栏 3991
上一篇: 孙鑫VC学习笔记:第十八讲 ActiveX 控件
下一篇: 孙鑫VC学习笔记:第二十讲 (一) Hook编程
Savitch
博客等级 码龄16年 84粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值