电信主站 网通分站
购买流程 付款方式 常见问题 在线提问 续租服务 购物车
用户名: 密 码: 忘记密码?
首 页
域名注册
虚拟主机
双线主机
服务器租用
VPS主机
企业邮局
代理专区
客服中心
虚拟主机行业资讯 虚拟主机评测对比 互联网最新动态 技术学院 站长资讯 在线教程 网站运营
搜索优化 服务器 网络编程 图形图象 站长之家 网页制作 操作系统
冲浪宝典 软件教学 视频通信 办公软件 邮件系统 网络安全 认证考试
您当前位置:西部数码->资讯中心-> 在线教程-> 数据库
Win32环境下动态链接库(DLL)编程原理-.NET教程,数据库应用
作者:网友供稿 点击:156
  西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!虚拟主机可在线rar解压,自动数据恢复设置虚拟目录等.虚拟主机免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金!
文章页数:[1] 
比较大应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作。其中可能存在一些模块的功能较为通用,在构造其它软件系统时仍会被使用。在构造软件系统时,如果将所有模块的源代码都静态编译到整个应用程序exe文件中,会产生一些问题:一个缺点是增加了应用程序的大小,它会占用更多的磁盘空间,程序运行时也会消耗较大的内存空间,造成系统资源的浪费;另一个缺点是,在编写大的exe程序时,在每次修改重建时都必须调整编译所有源代码,增加了编译过程的复杂性,也不利于阶段性的单元测试。

  windows系统平台上提供了一种完全不同的较有效的编程和运行环境,你可以将独立的程序模块创建为较小的dll(dynamic linkable library)文件,并可对它们单独编译和测试。在运行时,只有当exe程序确实要调用这些dll模块的情况下,系统才会将它们装载到内存空间中。这种方式不仅减少了exe文件的大小和对内存空间的需求,而且使这些dll模块可以同时被多个应用程序使用。microsoft windows自己就将一些主要的系统功能以dll模块的形式实现。例如ie中的一些基本功能就是由dll文件实现的,它可以被其它应用程序调用和集成。

  一般来说,dll是一种磁盘文件(通常带有dll扩展名),它由全局数据、服务函数和资源组成,在运行时被系统加载到进程的虚拟空间中,成为调用进程的一部分。如果与其它dll之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。dll模块中包含各种导出函数,用于向外界提供服务。windows在加载dll模块时将进程函数调用与dll文件的导出函数相匹配。

  在win32环境中,每个进程都复制了自己的读/写全局变量。如果想要与其它进程共享内存,必须使用内存映射文件或者声明一个共享数据段。dll模块需要的堆栈内存都是从运行进程的堆栈中分配出来的。

  dll现在越来越容易编写。win32已经大大简化了其编程模式,并有许多来自appwizard和mfc类库的支持。

  一、导出和导入函数的匹配

  dll文件中包含一个导出函数表。这些导出函数由它们的符号名和称为标识号的整数与外界联系起来。函数表中还包含了dll中函数的地址。当应用程序加载dll模块时时,它并不知道调用函数的实际地址,但它知道函数的符号名和标识号。动态链接过程在加载的dll模块时动态建立一个函数调用与函数地址的对应表。如果重新编译和重建dll文件,并不需要修改应用程序,除非你改变了导出函数的符号名和参数序列。

  简单的dll文件只为应用程序提供导出函数,比较复杂的dll文件除了提供导出函数以外,还调用其它dll文件中的函数。这样,一个特殊的dll可以既有导入函数,又有导入函数。这并不是一个问题,因为动态链接过程可以处理交叉相关的情况。

  在dll代码中,必须像下面这样明确声明导出函数:

__declspec(dllexport) int myfunction(int n);

  但也可以在模块定义(def)文件中列出导出函数,不过这样做常常引起更多的麻烦。在应用程序方面,要求像下面这样明确声明相应的输入函数:

__declspec(dllimport) int myfuncition(int n);

  仅有导入和导出声明并不能使应用程序内部的函数调用链接到相应的dll文件上。应用程序的项目必须为链接程序指定所需的输入库(lib文件)。而且应用程序事实上必须至少包含一个对dll函数的调用。

  二、与dll模块建立链接

  应用程序导入函数与dll文件中的导出函数进行链接有两种方式:隐式链接和显式链接。所谓的隐式链接是指在应用程序中不需指明dll文件的实际存储路径,程序员不需关心dll文件的实际装载。而显式链接与此相反。

  采用隐式链接方式,程序员在建立一个dll文件时,链接程序会自动生成一个与之对应的lib导入文件。该文件包含了每一个dll导出函数的符号名和可选的标识号,但是并不含有实际的代码。lib文件作为dll的替代文件被编译到应用程序项目中。当程序员通过静态链接方式编译生成应用程序时,应用程序中的调用函数与lib文件中导出符号相匹配,这些符号或标识号进入到生成的exe文件中。lib文件中也包含了对应的dll文件名(但不是完全的路径名),链接程序将其存储在exe文件内部。当应用程序运行过程中需要加载dll文件时,windows根据这些信息发现并加载dll,然后通过符号名或标识号实现对dll函数的动态链接。

  显式链接方式对于集成化的开发语言(例如vb)比较适合。有了显式链接,程序员就不必再使用导入文件,而是直接调用win32 的loadlibary函数,并指定dll的路径作为参数。loadlibary返回hinstance参数,应用程序在调用getprocaddress函数时使用这一参数。getprocaddress函数将符号名或标识号转换为dll内部的地址。假设有一个导出如下函数的dll文件:

extern "c" __declspec(dllexport) double squareroot(double d);

  下面是应用程序对该导出函数的显式链接的例子:

typedef double(sqrtproc)(double);
hinstance hinstance;
sqrtproc* pfunction;
verify(hinstance=::loadlibrary("c:\\winnt\\system32\\mydll.dll"));
verify(pfunction=(sqrtproc*)::getprocaddress(hinstance,"squareroot"));
double d=(*pfunction)(81.0);//调用该dll函数

  在隐式链接方式中,所有被应用程序调用的dll文件都会在应用程序exe文件加载时被加载在到内存中;但如果采用显式链接方式,程序员可以决定dll文件何时加载或不加载。显式链接在运行时决定加载哪个dll文件。例如,可以将一个带有字符串资源的dll模块以英语加载,而另一个以西班牙语加载。应用程序在用户选择了合适的语种后再加载与之对应的dll文件。

  三、使用符号名链接与标识号链接

  在win16环境中,符号名链接效率较低,所有那时标识号链接是主要的链接方式。在win32环境中,符号名链接的效率得到了改善。microsoft现在推荐使用符号名链接。但在mfc库中的dll版本仍然采用的是标识号链接。一个典型的mfc程序可能会链接到数百个mfc dll函数上。采用标识号链接的应用程序的exe文件体相对较小,因为它不必包含导入函数的长字符串符号名。



  四、编写dllmain函数

  dllmain函数是dll模块的默认入口点。当windows加载dll模块时调用这一函数。系统首先调用全局对象的构造函数,然后调用全局函数dllmain。dllmain函数不仅在将dll链接加载到进程时被调用,在dll模块与进程分离时(以及其它时候)也被调用。下面是一个框架dllmain函数的例子。

hinstance g_hinstance;
extern "c" int apientry dllmain(hinstance hinstance,dword dwreason,lpvoid lpreserved)
{
if(dwreason==dll_process_attach)
{
trace0("ex22a.dll initializing!\n");
//在这里进行初始化
}
else if(dwreason=dll_process_detach)
{
trace0("ex22a.dll terminating!\n");
//在这里进行清除工作
}
return 1;//成功
}

  如果程序员没有为dll模块编写一个dllmain函数,系统会从其它运行库中引入一个不做任何操作的缺省dllmain函数版本。在单个线程启动和终止时,dllmain函数也被调用。正如由dwreason参数所表明的那样。

  五、模块句柄

  进程中的每个dll模块被全局唯一的32字节的hinstance句柄标识。进程自己还有一个hinstance句柄。所有这些模块句柄都只有在特定的进程内部有效,它们代表了dll或exe模块在进程虚拟空间中的起始地址。在win32中,hinstance和hmodule的值是相同的,这个两种类型可以替换使用。进程模块句柄几乎总是等于0x400000,而dll模块的加载地址的缺省句柄是0x10000000。如果程序同时使用了几个dll模块,每一个都会有不同的hinstance值。这是因为在创建dll文件时指定了不同的基地址,或者是因为加载程序对dll代码进行了重定位。
模块句柄对于加载资源特别重要。win32 的findresource函数中带有一个hinstance参数。exe和dll都有其自己的资源。如果应用程序需要来自于dll的资源,就将此参数指定为dll的模块句柄。如果需要exe文件中包含的资源,就指定exe的模块句柄。

  但是在使用这些句柄之前存在一个问题,你怎样得到它们呢?如果需要得到exe模块句柄,调用带有null参数的win32函数getmodulehandle;如果需要dll模块句柄,就调用以dll文件名为参数的win32函数getmodulehandle。

  六、应用程序怎样找到dll文件

  如果应用程序使用loadlibrary显式链接,那么在这个函数的参数中可以指定dll文件的完整路径。如果不指定路径,或是进行隐式链接,windows将遵循下面的搜索顺序来定位dll:

  1. 包含exe文件的目录,
  2. 进程的当前工作目录,
  3. windows系统目录,
  4. windows目录,
  5. 列在path环境变量中的一系列目录。

  这里有一个很容易发生错误的陷阱。如果你使用vc++进行项目开发,并且为dll模块专门创建了一个项目,然后将生成的dll文件拷贝到系统目录下,从应用程序中调用dll模块。到目前为止,一切正常。接下来对dll模块做了一些修改后重新生成了新的dll文件,但你忘记将新的dll文件拷贝到系统目录下。下一次当你运行应用程序时,它仍加载了老版本的dll文件,这可要当心!

  七、调试dll程序

  microsoft 的vc++是开发和测试dll的有效工具,只需从dll项目中运行调试程序即可。当你第一次这样操作时,调试程序会向你询问exe文件的路径。此后每次在调试程序中运行dll时,调试程序会自动加载该exe文件。然后该exe文件用上面的搜索序列发现dll文件,这意味着你必须设置path环境变量让其包含dll文件的磁盘路径,或者也可以将dll文件拷贝到搜索序列中的目录路径下。


文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
相关主题
文章页数:[1] 
Google
热门文章
·数据库开发个人总结(ADO.NET小结)-.NET教程,数据库应用
·怎么由DataSet将数据导入Excel?-.NET教程,数据库应用
·动态创建SQL Server数据库、表、存储过程-ASP教程,数据库相关
·Win32环境下动态链接库(DLL)编程原理-.NET教程,数据库应用
·封装的ADO.NET对数据库操作经典类-.NET教程,数据库应用
·在DataGridView中获得DataGridViewCheckBoxColumn的状态-ASP教程,数据库相关
·DataGrid使用心得(附大量代码)-ASP教程,数据库相关
·用代码创建DataGrid的多链接及checkbox事件响应-.NET教程,数据库应用
·ADO.NET 的最佳实践技巧-.NET教程,数据库应用
·转载: 用纯ASP代码实现图片上传并存入数据库中

最新文章
·根据数据表中数据,生成Powerpoint幻灯片-ASP教程,数据库相关
·DataGrid中的按钮反选事件与NamingContainer(命名容器)-downmoon-ASP教程,数据库相关
·使用用VB处理MYSQL数据库中二进制数据问题-.NET教程,VB.Net语言
·关于DataGridView中如何接收处于编辑状态下的当前信息-ASP教程,数据库相关
·在DataGridView中获得DataGridViewCheckBoxColumn的状态-ASP教程,数据库相关
·.net下访问Access数据库需要注意的问题-.NET教程,Asp.Net开发
·ActiveMQ4.1+Spring2.0的POJO JMS方案(上)-.NET教程,数据库应用
·ASP.NET 2.0中直接将Access数据库导入到Excel文件中-.NET教程,Asp.Net开发
·NET(C#)连接各类数据库-集锦-.NET教程,C#语言
·ASP.NET2.0连接SQL Server数据库详解-.NET教程,Asp.Net开发


 
 


版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
  打印  刷新  关闭
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 虚拟主机 | 资讯中心 | 友情链接 | 网站地图

版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2006 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86262244 86263048 86263408 86263960 86264018 86267838
售前咨询:总机转201 202 203 204 206 208
售后服务:总机转211 212 213 214
财务咨询:总机转224 223 传真:028-86264041 财务QQ:点击发送消息给对方635483282
售前咨询QQ:点击发送消息给对方2182518 点击发送消息给对方241975952 点击发送消息给对方275026793 点击发送消息给对方408235859
售后服务QQ:点击发送消息给对方17708515 点击发送消息给对方307742704 点击发送消息给对方287976517 点击发送消息给对方363783715
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号