Dll:动态链接库

动态链接库(dll)是包含共享函数库的二进制文件,可以被多个应用程序同时使用。建立应用程序的可执行文件时,不必将DLL连接到应用程序中,而是在运行时动态装载DLL,装载时DLL被映射到调用进程的地址空间中。通常我们在调用DLL时所需的DLL文件必须位于以下三个目录之一:
——(1)Windows的系统目录:/windows/system;
——(2)DOS中path所指出的任何目录;
——(3)程序所在的目录; 

windows中有很多的dll文件,包括kernel.dll是内存管理的一些函数。含有图像处理的内存函数等等。

在VC中有两种导出函数的方法:

关键字_declspec  该方法比较简单。

模块定义文件。

dll主要有两部分组成,一是模块定义文件(.DEF),另一个是实现导出函数功能的源文件(C或C++文件)。函数分为内部函数和导出函数。

模块定义文件:

主要由语句说明:

1.LIBRARY 语句指出dll文件的名称。第一个语句必须是这个语句。

2.EXPORT语句指出被导出函数的名称。 EXPORT Add(),必备语句

3.可以使用DESCRIPTION语句对dll的用途进行说明,这个是可选项。

4.“;”对一行进行注释,可选项。

实现源文件:

实现入口函数的.cpp或.c文件,包括dll入口点的API函数和导出函数的代码。

在VC中好像很简单,并不需要写def,

我使用的是Visual C++ 2008 express  Edition,当我新建一个工程时,选择编写dll文件,直接生成很多文件,包括dll入口文件dllmain.cpp和stdafx.cpp。和源文件sample.cpp以及头文件targetver.h  stdafx.h,sample.h。

在dllmain.cpp中:

一个DLL必须有一个入口点,这就象我们用C编写的应用程序一样,必须有一个WINMAIN函数一样。

DllMain是一个缺省的入口函数,你不需要编写自己的DLL入口函数,并用linker的命令行的参数开关/ENTRY声明。用这个缺省的入口函数就能使动态连接库被调用时得到正确的初始化,当然了,你不要在初始化的时候填写使系统崩溃的代码了。参数中,hMoudle是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符)ul_reason_for_call是一个说明动态库被调原因的标志。当进程或线程

装入或卸载动态连接库的时候,操作系统调用入口函数,并说明动态连接库被调用的原因。它所有的可能值为:

DLL_PROCESS_ATTACH: 进程被调用

DLL_THREAD_ATTACH: 线程被调用

DLL_PROCESS_DETACH: 进程被停止

DLL_THREAD_DETACH: 线程被停止

lpReserved是一个被系统所保留的参数。

由于相同的原因,多个应用程序还可以同时共享DLL在内存中的同一份拷贝,这样就有效的节省了应用程序所占用的内存资源,减少了频繁的内存交换,从而提高了应用程序的执行效率。
由于DLL是独立于可执行文件的,因此,如果需要向DLL中增加新的函数或是增强现有函数的功能,只要原有函数的参数和返回值等属性不变,那么,所有使用该DLL的原有应用程序都可以在升级后的DLL的支持下运行,而不需要重新编译。这就极大的方便了应用程序的升级和售后支持。
DLL除了包括函数的执行代码以外,还可以只包括如图标、位图、字符串和对话框之类的资源,因此可以把应用程序所使用的资源独立出来做成DLL。对于一些常用的资源,把它们做到DLL中后,就可为多个应用程序所共享。
便于建立多语言的应用程序。我们可以把多语言应用程序中所使用的与语言相关的函数做到DLL中,只要不同语言的应用程序所调用的函数都具有相同的接口,这样就可以通过简单地更换DLL来实现多语言支持。

sample.h

这是VC提供的一个关键字,用它可在动态连接库中输出一个数据、一个函数或一个类。用这个关键字可省你不少事,你不用在.DEF文件

中说明我要输出这个类、那个函数的.

#ifdef FIRST_EXPORTS

#define FIRST_API __declspec(dllexport)

#else

#define FIRST_API __declspec(dllimport)

#endif

// This class is exported from the First.dll

class FIRST_API CFirst {

public:

CFirst(void);

// TODO: add your methods here.

};

extern FIRST_API int nFirst;

extern “C" FIRST_API int fnFirst(void);

编写DLL文件和调用DLL文件总结:

1、编写时要编写源文件和头文件。源文件定义函数原型、类。

如果是C++,可以定义类

如果是C,注意要以C的方式编译,要加上 extern “C”(这个很关键,否则利用取地址函数不分配函数地址,刚开始就这犯错误了)

2.在调用程序中,要设置函数指针。以及调用指针

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

phai hai;//函数指针

HINSTANCE hDLL=NULL;

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

if (hDLL==NULL)

{

printf("Can not open");

return 0;

}

printf("test");

hai=(phai)GetProcAddress(hDLL,"Sum");

HINSTANCE 是“句柄型”数据类型。相当于装入到了内存的资源的ID。HINSTANCE对应的资源是instance.句柄实际上是一个 无符号长整数。但它是“句柄型”,所以你不能把它当成真的无符号长整数,拿来派别的用处,例如,不能拿来做四则运算。HINSTANCE常出现在 API 程序。

HMODULE 是代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址

HINSTANCE 在win32下与HMODULE是相同的东西,在Win32下还存在主要是因为win16

对于DLL的调用有两种:显示调用和隐式调用。

我前面所说的是显示调用,这种方法不需要.lib文件。头文件中要包含windows.h,#include "windows.h"

这种调用方式是指在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显式的将自己所做的动态连接库调进来,并指定DLL的路径作为参数。LoadLibary返回HINSTANCE参数,应用程序在调用GetProcAddress函数时使用这一参数。当完成对动态链接库的导入以后,再使用GetProcAddress()获取想要引入的函数,该函数将符号名或标识号转换为DLL内部的地址,之后就可以象使用本应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或MFC提供的AfxFreeLibrary释放动态连接库。

隐式的调用
这种调用方式需要把产生动态连接库时产生的.LIB文件加入到应用程序的工程中,在使用DLL中的函数时,只须说明一下后就可以直接通过函数名调用DLL的输出函数,调用方法和程序内部其他的函数是一样的。隐式调用不需要调用LoadLibrary()和FreeLibrary()。程序员在建立一个DLL文件时,链接程序会自动生成一个与之对应的LIB导入文件。该文件包含了每一个DLL导出函数的符号名和可选的标识号,但是并不含有实际的代码。LIB文件作为DLL的替代文件被编译到应用程序项目中。
  当程序员通过隐式调用方式编译生成应用程序时,应用程序中的调用函数与LIB文件中导出符号相匹配,这些符号或标识号被写入到生成的EXE文件中。LIB文件中也包含了对应的DLL文件名(但不是完全的路径名),链接程序也将其存储在EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows根据这些信息发现并加载DLL,然后通过符号名或标识号实现对DLL函数的动态链接。所有被应用程序调用的DLL文件都会在应用程序EXE文件加载时被加载在到内存中。

隐式链接要链接相应的lib文件,在调用程序中,要包含对应dll文件的头文件(该头文件有相应函数和类的说明),不需要有windows.h头文件。

dll学习的更多相关文章

  1. NPOI.dll学习

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. 简介 编辑 使用 NPOI 你就可以在没有安装 Office 或者相应环 ...

  2. DLL学习笔记一(DLL导入导出)

    创建DLL: 先声明导出函数:使用__declspec(dllexport) #include"DLLSample.h" #ifndef _DLL_SAMPLE_H #define ...

  3. Dll学习(二)__declspec用法详解

    __declspec用于指定所给定类型的实例的与Microsoft相关的存储方式.其它的有关存储方式的修饰符如static与extern等是C和 C++语言的ANSI规范,而__declspec是一种 ...

  4. dll 学习(一)

    DLL(Dynamic Link Library)的概念,你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量.函数或类.在仓库的发展史上经历了"无库-静态链接库-动态链接库 ...

  5. Dll学习三_Dll 相互间以及主程序间的数据共享——测试未通过,应该用内存映射

    测试环境:XP,DELPHI XE 验证通过结构:主程序+一个Dll窗体 共享方式原理:通过主程序与各Dll定义相同的参数结构体,由主程序实例化该结构体,对于各Dll间的共享,通过传主程序实例化的结构 ...

  6. Dll学习二_Dll 窗体中动态创建数据并使用Demo

    沿用上一篇Demo 环境:DelphiXE,XP,SQL2005 贴出改动过的单元代码: dbGrid控件版: unit SubMain_Unit; interface uses Windows, M ...

  7. Dll学习一_Dll 创建并动态引用窗体且释放窗体Demo

    1.新建Dll工程 2.Dll工程全部代码 library SubMain; { Important note about DLL memory management: ShareMem must b ...

  8. c#利用SWIG调用c++dll学习总结【转】

    开发环境: 操作系统:windows 7 IDE:Microsoft Visual Studio Professional 2015 SWIG: 3.0.12 swig的介绍 详细介绍可看官网,一下贴 ...

  9. weiFenLuo.winFormsUI.Docking.dll学习

    引用方法: 1.建立一个WinForm工程,默认生成了一个WinForm窗体. 2.引用—>添加引用—>浏览—>weiFenLuo.winFormsUI.Docking.dll. 3 ...

随机推荐

  1. solarium atomic update

    https://github.com/solariumphp/solarium/issues/159

  2. 实现LRU的两种方法---python实现

    这也是豆瓣2016年的一道笔试题... 参考:http://www.3lian.com/edu/2015/06-25/224322.html LRU(least recently used)就不做过多 ...

  3. kegg-kass注释--转载

    在注释KEGG的时候,一直用到kaas,具体kaas是个什么东东,简单的总结一下吧.     KEGG是由日本人搞的一个代谢图,收录基因和基因组的数据库,数据库可以分为 3大部分,基因数据库, 化学分 ...

  4. Mac 安装 MySQL

    在 Mac 下用 Homebrew 安装 MySQL, 网上的教程倒是很多,不过大多数都很默契地雷同.如果稍有点定制要求,就无从下手了. 我先也不免俗,从基本的开始: 一.首先安装 Homebrew ...

  5. Openfire基础

    网上很多openfire相关资料,这里做下学习汇总 openfire官网:http://www.igniterealtime.org/ 可以下载openfire.spark.smack安装包及源码,安 ...

  6. TestNG Study Note 1 - Eclipse 插件安装

    TestNG 插件在线安装 Help -> Install New Software -> Add -> Paste TestNG url to Add:  http://testn ...

  7. Linux 命令——grep | 正则表达式

    感觉讲的很详细,瞬间懂了grep,正则. from: here 简介 grep (global search regular expression(RE) and print out the line ...

  8. C#操作SQL Server数据库

    http://www.cnblogs.com/rainman/archive/2012/03/13/2393975.html

  9. linux command

    ubuntu start network:sudo service network-manager start

  10. 组件嵌套+Mixin函数demo

    非DOM属性:1.dangerouslysetInnerHTML(xxs跨站攻击) 2.key 3.ref 编写组件嵌套 <!DOCTYPE html><html>  < ...