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. 安装配置dradis

    github:https://github.com/dradis/dradis-ce/blob/master/README.md安装出现错误:== Copying sample files == == ...

  2. nignx 负载均衡的几种算法介绍

    负载均衡,集群必须要掌握,下面介绍的负载均衡的几种算法.   1 .轮询,即所有的请求被一次分发的服务器上,每台服务器处理请求都相同,适合于计算机硬件相同.   2.加权轮询,高的服务器分发更多的请求 ...

  3. WCF入门简单教程(图文) VS2010版

    在这个例子中我们将使用VS 2010 创建一个WCF服务,其中会了解 [DataContract] [ServiceContract] 等特性.  内置的 WCFSVCHost ,并使用“WCF测试客 ...

  4. solr 3.5.0 与 tomcat 7.0.5 整合配置

    1.将D:\software\lucene-3.6.0\apache-solr-3.5.0\example\solr下的文件拷贝到要作为服务器的位置(如:D:\lucene\solr\home),可以 ...

  5. Bootstrap之Carousel不能自动播放的解决办法(转)

    Bootstrap是一个非常好的css/javaScript框架,尤其对于移动端的自适应和适配能力都比较强. 用Bootstrap自带的Carousel写了一个图片轮播的广告部分,用js调用后却出现了 ...

  6. indexOf 用法

    一.字符串的IndexOf()方法: (括号里的为子字符串) 搜索在该字符串上是否出现了作为参数传递的子字符串,如果找到子字符串,则返回子字符串在该字符串上出现的起始位置 (0表示第一个字符,1表示第 ...

  7. C# 发送qq邮箱

    注意: QQ邮箱的简单邮件传输协议(SMTP)使用了SSL加密,必须启用SSL加密.指定端口. QQ邮箱POP3/SMTP服务默认是关闭的,需要开启服务(设置=>账户=>开启服务). QQ ...

  8. Java之工厂方法

    普通工厂模式: 第一步:定义接口,坚持面向接口编程, package dp; public interface Sender {    public void send();} 第二步:实现接口: p ...

  9. MySQL问题记录--python插入中文至MySQL提示SQLErroor:1366错误

    一.在爬虫脚本做以下操作仍提示错误:SQL Error: 1366: Incorrect string value: "\xd0\xc2\xce\xc5-" for column  ...

  10. loadrunner随笔1

    快捷键: 注释快捷键:  ctrl+alt+c 取消注释快捷键:ctrl+alt+u 开始录制快捷键: ctrl+r 运行时设置快捷键: f4 录制设置: ctrl + f7 查找和替换:ctrl + ...