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年11月15日
    44
  • mysql慢查询优化方法_MySQL查询优化

    mysql慢查询优化方法_MySQL查询优化定位低效SQL执行慢有两种情况:偶尔慢:DB在刷新脏页redolog写满了内存不够用,要从LRU链表中淘汰MySQL认为系统空闲的时候MySQL关闭时一直慢的原因:索引没有设计好、SQL语句没写好、MySQL选错了索引’mysql慢查询优化第一步:开启mysql慢查询日志,通过慢查询日志定位到执行较慢的SQL语句。第二步:利用explain关键字可以模拟优化器执行SQL查询语句,来分析SQL查询语句。第三步:通过查询的结果进行优化。优化方式(1)首先分

    2022年10月10日
    1
  • 网络RJ45接口详解[通俗易懂]

    网络RJ45接口详解[通俗易懂]RJ45简介图1RJ45模块RJ45模块用于实现PHY之间的互连,包括PHY芯片经信号变压器与RJ45接口相连,如图1所示。RJ45连接器由插头和插座组成,RJ45插头又称水晶头,如图3-10所示。这两种元件组成的连接器连接于导线之间,以实现导线的电气连续性。RJ45连接器就是连接器中的最重要的一种插座。RJ45插座分屏蔽型和非屏蔽型两种。RJ是RegisteredJack的…

    2022年9月17日
    1
  • 秒秒钟解决打开ps图片显示无法完成请求,因为程序错误「建议收藏」

    秒秒钟解决打开ps图片显示无法完成请求,因为程序错误「建议收藏」问题描述今天在做ps作业的时候做到一半,保存的时候卡了一下,我等了一会,不卡了,我以为我保存了就没什么事了,然后就关闭ps,软件关闭的时候也卡了一下,结果现在想接着做的时候打不开了,做了那么久那么多图层都在,我心态直接崩了,白做了。当我赶紧上网查怎么修复和解决。全特码是p话,一个有用的都没有,说什么右键ps属性,兼容性的运行,管理员打开,设置好后就可以直接打开了,我特么又不是兼容性的问题,之前一直用的好好的,还有打开ps清理暂存盘,缓存大小改大,我。。。。。。呵呵。还有说检查ps是否更新了,说什么确保系.

    2025年5月25日
    2
  • Python正则表达式_正则表达式有什么用

    Python正则表达式_正则表达式有什么用定义:正则表达式是对字符串(包括普通字符(例如,a到z之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。上面都是官方的说明,我自己的理解是(仅供参考):通过事先规定好一些特殊字符的匹配规则,然后利用这些字符进行组合来匹配各种复杂的字符串场景。比如现在的爬虫和数据分析,字符串校验等等都需要用

    2022年10月3日
    2
  • SQL Server 最小化日志操作解析,应用

    SQL Server 最小化日志操作解析,应用

    2022年3月6日
    43

发表回复

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

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