12、动态链接库,dll

12、动态链接库,dll

动态链接库通常都不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数。只有在其它模块调用动态链接库中的函数时,它才发挥作用。

1、我们可以把完成某种功能的函数放在一个动态链接库中,提供给其它函数调用。Windows API中所有的函数都包含在DLL中,其中三个最重要:

1Kernal32.dll 包含那些用于内存管理,进程和线程的函数,如CreateThread函数。

2User32.dll 包含执行用户界面任务,如窗口的创建和消息的传送的函数,如3CreateWindow函数。

3GDI32.dll 用于画图的显示文本的函数。

2、静态库与动态库:

静态库:

函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件。产品发布时不需要发布被使用的静态库。

动态库:

动态库一般提供两个文件:一个引入库(.lib,一个是DLL.dll)文件。.lib文件中包含该DLL导出的函数和变量的符号名,而.dll文件包含该DLL实际的函数和数据。在使用动态库情况下,在编译链接可执行文件时,只需要链接该DLL的引入库文件,该DLL中的函数代码和数据并不复制到可执行文件中,直到可执行程序运行时,才去加载所需的DLL,将该DLL映射到进程的地址空间中,然后访问DLL中导出的函数。发布产品时要同时发布 DLL

wps_clip_image-28821

图示 P703 两个进程访问同一个DLL时的情形

两种加载dll文件的方式,隐式加载和显式加载。

3Dumpbin命令

应用程序如果想要访问某个DLL中的函数,那么该函数必须是已经被导出的函数。可以用Dumpbin查看。在使用之前可能需要通过VCVARS32.bat来建立VC使用的环境变量。

dumpbin -exports name.dll

4、导出DLL中函数

_declspec(dllexport)于函数前面。

1)隐式加载

1)通过extern声明外部函数。并在工程属性的链接器的命令行中输入lib符号名文件。把dll文件和lib文件放入指定目录中在工具选项的VC++目录中包含。

2)利用_declspec(dllimport)于外部函数声明前。

为了方便dll的使用,通常都是提供一个.h文件给客户的;我们通常在头文件的函数声明按如下形式处理:


#ifdef DLL1_API
#else
#define DLL1_API _declspec(dllimport)
#endif

DLL1_API int _stdcall add(int a,int b);

而在函数定义的
.cpp
文件中,如下形式定义:


#define DLL1_API extern "C" _declspec(dllexport)
#include "Dll1.h"

#include <Windows.h>
#include <stdio.h>

int _stdcall add(int a,int b)
{
return a+b;
}

这样提供给客户时不需要额外的改动代码。

同样,可以把上面定义的DLL1加在一个类前面,或类的成员函数前面来把类或类的成员函数导出。如下所示:

class /*DLL1*/ Point
{
public:
void DLL1_API output(int x,int y);
void test();
};



2)显式加载

通过LoadLibrary来实现。LoadLibrary将指定的可执行模块映射到调用进程的地址空间,and the return value is a handle to the module。再通过GetProcAddress 来获得动态库中导出函数的地址。

HINSTANCE hInst;
hInst=LoadLibrary("Dll3.dll");
typedef int (/*_stdcall*/ *ADDPROC)(int a,int b);
//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"?add@@YAHHH@Z");
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");
//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));


The MAKEINTRESOURCE macro converts an integer value to a resource type

compatible with the resource-management functions. This macro is used in place of a

string containing the name of the resource

The DllMain function is called when the driver DLL first starts up.

使用完后,通过FreeLibrary 来减少被加载的dll的引用计数,当减到0时,该DLL模块从调用进程的地址空间卸载。

5、名字改编问题

不同的编译器在编译函数时,及采用不同的函数调用约定时,对函数的改编是不一样的。

http://www.cnblogs.com/mydomain/archive/2010/09/27/1837179.html

由此,在函数调用时会产生一些问题,如用C++编译器生成的函数通过C编译器调用时会出错。对于这种情况,可以在声明中加上extern “C”

#define DLL1_API extern “C” _declspec(dllimport)

利用extern “C”可以解决C++,C间相互调用问题,但是有一个缺陷,就是不能用于导出一个类的成员函数。,只能用于导出全局函数这种情况。

如果函数的调用约定发生了变化,如有的函数用_stdcall,有的用pascal,那么即使使用了extern “C”,名字改编仍会发生。

可以通过定义一个模块定义文件.def的方式来解决这个问题:

新建一个newname.def文件,加入工程中:


LIBRARY Dll2
EXPORTS
add
subtract

Dll2
与生成的动态链接库名相同。

EXPORTS:下面定义的符号名如果与函数名一样,则以符号名导出函数,如果不同,按下面规则导出函数:

entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE]

There are three methods for exporting a definition, listed in recommended order of use:

1.The __declspec(dllexport) keyword in the source code

2.An EXPORTS statement in a .def file

3.An /EXPORT specification in a LINK command[1]

参考:

[1] http://msdn.microsoft.com/en-us/library/hyx1zcd3.aspx

[2] VC++深入详解

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110679.html原文链接:https://javaforall.net

(0)
上一篇 2021年8月9日 下午2:00
下一篇 2021年8月9日 下午3:00


相关推荐

  • HashMap遍历以及遍历顺序[通俗易懂]

    HashMap遍历以及遍历顺序[通俗易懂]HashMap遍历以及遍历顺序HashMap是Java语言中一种键值对(key-value)数据结构,但不记录key的插入顺序,如果要按照插入顺序进行遍历,则需要使用LinkedHashMap类型。本文将介绍下HashMap的三种遍历方式,LinkedHashMap遍历方式相同!(在leetcode12.整数转罗马数字题目中使用到HashMap遍历,遂做此记录!)HashMap结构定义如下:Map<Integer,String>map=newHashMap<Inte

    2025年10月15日
    6
  • 动态加载页面怎么抓取数据?深度解析从 DOM 陷阱到视觉 AI 的架构突破

    动态加载页面怎么抓取数据?深度解析从 DOM 陷阱到视觉 AI 的架构突破

    2026年3月19日
    2
  • java 面试题详解(转自传智播客张孝祥老师)

    java 面试题详解(转自传智播客张孝祥老师)张孝祥正在整理 Java 就业面试题大全 每天进步一点点 CSDN 博客 2011 年 11 月 24 日星期四设为主页加入收藏帮助 留言交流 登录首页阅览室馆友我的图书馆张孝祥正在整理 Java 就业面试题大全 每天进步一点点 CSDN 博客 转载 asdfg 收藏于

    2025年8月24日
    7
  • FMX探索之FMX下绘文字绘制

    FMX探索之FMX下绘文字绘制Delphi 版本已升级到 10 1 经过官方的不断努力 版本也趋于稳定 在跨平台及 Anroid 开发方面的进步确定非常大 因此本人也开始尝试学习 FMX 尝试移动开发 使用 Delphi 工具入门真的非常之精简 随便拖几个控件 切换下编译平台 点击运行 就要以在各个平台上跑起来 但是今天在尝试在窗体上输出文字时 给难住了 在 VCL 下 代码是这样的 procedureTFo Button1

    2026年3月18日
    2
  • mysql连接池DruidDataSource的使用、配置「建议收藏」

    mysql连接池DruidDataSource的使用、配置「建议收藏」记录一下使用DruidDataSource的常用配置。1.pom.xml中引入:<!–https://mvnrepository.com/artifact/com.alibaba/druid–><dependency><groupId>com.alibaba</groupId&g…

    2022年7月23日
    13
  • ps磨皮滤镜插件Portraiture 3

    ps磨皮滤镜插件Portraiture 3Photoshop必备滤镜插件,Portraiture3formac(ps磨皮滤镜插件)是一款支持自动皮肤平滑、愈合和增强效果的磨皮插件,portraiture3主要针对人像进行皮肤修饰、磨皮润色等处理,还可以平滑和去除缺陷,同时保留皮肤纹理和重要的人像细节,功能十分强大,安装即为激活成功教程版。ps磨皮滤镜插件特色介绍Photoshop的画像消除了选择性蒙版和逐像素处理的繁琐的手工劳动,以帮助您在肖像修饰中实现卓越。Imagenomic发布了Photoshop的磨皮滤镜Portraiture

    2022年7月22日
    19

发表回复

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

关注全栈程序员社区公众号