DLL的心得体会

关于DLL,网上的资料很多,也很杂乱,我花了一天的时间,把各种版本都亲手试了试。加上自己的心得和体会,还是挺全面的。希望能对大家有所帮助。

DLL:动态链接库。

DLL是与exe分开的,当exe执行的时候才去找DLL中函数,而普通的lib文件是链接的时候就已经加载到exe中的。

动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。

动态链接与静态链接的不同之处在于:动态链接允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。

Lib文件是已经编译好的,但没有链接,所以程序链接的时候就会去找lib

Dll文件是已经编译好,且链接好的,所以程序编译和链接的时候都和它没关系,只有执行的时候才去找他。

应用程序和 DLL 之间的区别

应用程序可有多个同时在系统上运行的实例,而 DLL
只能有一个实例。

应用程序可以拥有堆栈、共用内存、文件句柄、消息队列这样的事物,而 DLL
不能。

使用 DLL 的优点

1节省内存和减少交换操作。很多进程可以同时使用一个 DLL,在内存中共享该 DLL
的一个副本。相反,对于每个用静态链接库生成的应用程序,Windows
必须在内存中加载库代码的一个副本。

2节省磁盘空间。许多应用程序可在磁盘上共享 DLL
的一个副本。相反,每个用静态链接库生成的应用程序均具有作为单独的副本链接到其可执行图像中的库代码。

3升级到 DLL
更为容易。当 DLL
中的函数发生更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。相反,静态链接的对象代码要求在函数更改时重新链接应用程序。

4提供售后支持。例如,可修改显示器驱动程序 DLL
以支持当初交付应用程序时不可用的显示器。

5DLL可以被其他DLL调用,而lib库不可以被其他lib调用。

生成DLL文件

有两种方法:

在生成 DLL
时,创建一个模块定义 (.def)
文件并使用该 .def
文件。。

在函数的定义中使用 __declspec(dllexport) 关键字。

在此之前我们要创建一个DLL工程:new project->C++->win32 consoleapplication->DLL->文件名:Mydll

Dllmain.cpp是入口函数,不用管。主要是在Mydll.cpp中写代码

1. 使用__declspec(dllexport) 关键字生成DLL

若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。

若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边。

例如:该动态链接库中有两个函数,分别用来实现得到两个数的最大和最小数。

//Mydll.h

extern "C" _declspec(dllexport) int Max(int a, intb);

extern "C" _declspec(dllexport) int Min(int a, intb);

//Mydll.cpp

#include”Mydll.h”

int Max(int a, int b)

{

if(a>=b)returna;

else

return b;

}

int Min(int a, int b);

{

if(a>=b)returnb;

else

return a;

}

然后build一下,就在debug中生成了Mydll.dll和Mydll.lib文件。

2. 使用def文件生成DLL

在Mydll.cpp中写好自己要导出的函数(或类或变量)的定义.就是普通定义,不加什么修饰符的。

然后new一个def文件,在def文件中写:

LIBRARY MyDll(是包含要导出函数的文件名)

EXPORTS

函数名(要导出的函数名,可以有多个)

函数名

然后build一下,就在debug中生成了Mydll.dll和Mydll.lib文件。

注:这里为何生成了lib文件?

这里的lib文件是DLL文件中函数名称和地址,如果是隐式链接的话,链接的时候程序会链接DLL的导入库文件(就是这个lib文件)。在程序执行时,程序才会根据导入库文件中的函数地址去到DLL中寻找函数体。

DLL<-----àLIB<-----àEXE

注:DLL内部函数的调用是不用加什么_declspec(dllexport)的,想一想DLL的原理就知道原因了。

链接DLL的方法(如何使用DLL)

注:编译时是和库文件没有关系的

有两种类型的链接:隐式链接和显式链接。(隐式链接要把生成DLL的程序会产生DLL文件和导入文件lib放到当前工程目录下,显示链接只需要DD文件就可以了)

隐式链接:

隐式链接就是在程序开始执行时就将DLL文件加载到应用程序当中。实现隐式链接很容易,只要将导入函数关键字_declspec(dllimport)函数名等写到应用程序相应的头文件中就可以了。

为隐式链接到 DLL,可执行文件必须从 DLL
的提供程序获取下列各项:

1包含导出函数和/或 C++
类的声明的头文件(.h
文件)。使用__declspec(dllimport)

将函数的定义导入进来

2要链接的导入库(.LIB
files
)。(生成 DLL
时链接器创建导入库。)

3实际的 DLL(.dll
文件)。

例如:

// TestDll.h

#pragma comment(lib,"MyDll.lib")

!!这一步开发人员也可以不使用#pragma comment(lib,"MyDll.lib")语句,而直接在工程的Setting->Link页的Object/Moduls栏填入MyDll.lib既可

extern "C" _declspec(dllimport) int Min(int a,intb);

!!如果要导出的是变量:则

extern _declspec(dllimport) inta;因为只有加上extern,这才是声明。

这部分也可以用

extern “ C” {

#include”Mydll.h”

}

来代替,效果是一样的。(注意要把MyDll.h拷到此工程下).推荐这样使用。

//TestDll.cpp

#include<iostream>

#include<Windows.h>

#include"Dlltest.h"

void main()

{int a;

a=Min(8,10)

cout<<a<<endl;

}

/////////////////////////////////////////////////////////////

静态链接体会:

1. Dll和lib不是都已经有了吗,为何还需要#include<.h>或dllimport。

因为dll需要静态导入,所以需要lib导入库,由于lib导入库中的函数名都是c编译好的,函数名都是_funcname形式的,所以需要#include<..h>或dllimport函数名,这样编译时才会生成函数名类似_funcname形式的。然后链接时才会正确链接lib导入库。

2. 为何#include头文件中要加extern “C”或者_declspec(dllimport)前要加extern “C”。

因为lib导入库是用C语言编译好的,函数名形如_funcname.如果用C++来编译头文件或_declspec(dllimport)后面的函数名,由于C++支持多态,所以它编译函数名时要把函数的参数个数、参数类型一起柔和在一起,则函数名会是_func_int_float类似的东西。而这样的函数名显示与lib导入库的函数名匹配不了的。

//////////////////////////////////////////////////////////////

显式链接:

显式链接是应用程序在执行过程中随时可以加载DLL文件,也可以随时卸载DLL文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,对于解释性语言更为合适。

在显式链接下,应用程序必须进行函数调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:

1调用 LoadLibrary(或相似的函数)以加载
DLL 和获取模块句柄。

2调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用
DLL 的函数,编译器不生成外部引用,故无需与导入库链接。

3使用完 DLL
后调用 FreeLibrary。

#include<iostream>

#include<Windows.h>

using
namespace std;

void main(void)

{

typedef int(*pMax)(int a,int b);

HINSTANCE hDLL;

pMax Max;

hDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;

Max=(pMax)GetProcAddress(hDLL,"Max");

int a=Max(5,8);

cout<<a<<endl;

FreeLibrary(hDLL);//卸载MyDll.dll文件;

System(“pause”);

}

!!!!

查看lib文件、dll文件,使用命令行:

>dumpbin /exports xxx.lib/xxx.dll

时间: 2024-08-30 15:39:09

DLL的心得体会的相关文章

编程方法心得体会

编程学习心得和方法(转载,供新手参考)   即便是高级编程人员,像那些为开发软件工作的类库和组件高手,他们也不敢说自己精通每一种语言. 事实就是这样,每一种语言有着它们相似而又不同的语法,它们有着不同的关键字,发展出了各种各样的类库,它们的函数或者方法的声明定义都有不同,更多的差异不为我们所知. 每一种语言,它都有着太多的东西需要我们去理解和记忆,我们没有时间和精力做得太多. 对于初学者,我们最不应该急于求成,更不要试图一次性学习所有语言.事实上,我们可以选取某种语言学习.每一种语言都有着自己的

AngularJS心得体会

AngularJS早些时候有过了解,知道这是一个JS的MVC框架,同类型的框架还有Backbone等.这次是由于项目需要,学习了两天的Angular后开始着手改之前的项目代码,这里大概说一下这一周学习Angular的心得体会吧. 首相,使用Angular最大的感受就是它的设计思路完全不同于Jquery,jquery更倾向于对Dom的操作:而使用Angular则需要你有一个全局的认识,你必须知道你想要做成什么样子才可以下手去做,所以我感觉ng对前端开发的要求比jquery要高一些.先来看看Angu

关于软件项目管理的心得体会之一

目的 软件项目管理是一项涉及面较广,但是非常必要的一项技能.相较于软件开发中的其他专业技能, 又更加依赖于实践和阅历.这里想跟各位同仁分享一下自己在过往项目中的心得体会,结合些许耳熟能详的理论,起到抛砖引玉的作用. 局限性 项目管理既然是一门实践科学,所以这里跟大家分享之前,还是要说明局限性.因为我之前是在一家提供软件服务的传统软件公司工作, 所以很多项目的经验都来源于作为乙方的外包项目,同时,大部分项目都是移动相关领域.目前我在一家国内的互联网公司,从事的电商相关的应用项目. 开篇 想跟大家分

读《构建之法》的心得体会

读<构建之法>的心得体会 软件工程涉及的范围很广,对于即将投身IT业的学生而言,软件工程的内容又非常重要.读构建之法,尽管本书介绍了不少IT业正在使用的理论和技术,但是,这本书的主要思想并不是介绍所有的新思想和新技术,而是从这些新思想.新技术中总结出对自己在未来的工作中有用的东西. 在整本书中,印象最让我深刻的是“两个人的合作”这一章节.现代的软件产业经过几十年的发展,软件的结构随着用户需求的不断增加,软件的功能不断朝多元化与复杂化发展.不管是两个人的合作还是团队的合作,谈到合作不免提及规范这

Git的基本使用方法和安装&amp;心得体会

1. git的安装和github的注册.代码托管.创建organization.邀请member. (1)git的安装 因为我电脑是windows系统,所以下载的是git for windows.在官网下载非常卡,直接百度搜找百度那个下载就可以.下载后选择路径一直next就行了. (2)github的注册 没什么说的,虽然界面是英文,不过要是连这种程度的都看不懂你还是洗洗睡吧.按要求填完邮箱账号密码等常规东西就注册完了. (3)创建organization the organization's

IT增值服务实践心得体会:企业客户的钱比个人客户好赚得多

友情提示 本人喜欢直言不讳,不喜欢拐弯抹角.喜欢从客观和主观.自身和他人等多种角度去探讨问题.如有不当之处,欢迎吐槽. 若干心得体会1.企业客户的钱更好赚,个人客户的钱很难.  为什么这么说呢? a.企业有钱赚,为了更好地服务自己的客户,赚到更多的钱,花点钱,心甘情愿.只要你的商品和服务,不至于太坑. b.企业的功利心比较强,因此,非常有目标性,有动力,一定要解决自己遇到的问题. c.个人的付费意识很差,因为他们总认为自己赚的钱少,同时下意识地认为,别人花时间精力提供的服务或者劳动成果,不值钱.

关于代码的一些心得体会(大神勿喷)

关于代码的一些心得体会   前  言 Lms 入行也有很久了,一直都只是忙着工作学习,却一直没能好好静下心来好好整理一下自己.时间久了,慢慢的代码越来越熟悉,敲起来也越来越顺手,自己缺总感觉有些不对.我总觉得代码不应该就是这么简单,不应该像写记叙文一样,一条一条慢慢的就罗列出来了,返回去看了看自己刚写代码的时候功能也都能够实现了.但是还是有那么多可以优化的地方.我觉得好的代码不应该只是把功能实现那么简单,我觉得好的代码应该有以下几条特点:第一,命名要规范,第二,可复用性,第三,就是注释.当然,当

第8章 让开发板发出声音,蜂鸣器驱动 心得体会

第8章让开发板发出声音,蜂鸣器驱动 心得体会 通过学习Android深度探索(卷1)HAL与驱动开发的第8章 让开发板发出声音,蜂鸣器驱动,我加深对驱动的认识.以下主要是我对本节实验和参考在Linux驱动开发中使用PWM控制蜂鸣器中的一些见解. 先编写一个简单的蜂鸣器驱动程序,根据开发板上的硬件IO接口和Android驱动规范,在kernel中的driver目录中新建一个Buzzer文件,新建一个buzzer.c的源文 在目录下创建一个Makefile文件 先运行make clean命令清楚到编

大道至简第一章心得体会

大道至简——编程的精义  心得体会      谨以此用于苦恼编程序不得入门的人,不对之处敬请指出 “虽我之死,有子存焉:子又生孙,孙又生子:子又有子,子又有孙.子子孙孙,无穷匮也.而山不加增,何苦而不平?” ——<愚公移山>,<列子-汤问篇> 编程究其本身对大数人而言是一件很苦恼而又无法避免的事情,但是有点可笑的是编程本身实在是一件简单的事,因为“程序=算法+结构”,所谓的编程就是把一件事情交给计算机去做,然后把你的想法“告诉”计算机就行了.但是编程又是一件很“无语”的事情——因为