Visual C++ dll编程
作者&投稿:易饱 (若有异议请与网页底部的电邮联系)
新建win32工程,向导里面选择dll
两种常用方法
1、使用命令提示符下的dumpbin格式如下
dumpbin -exports xxx.dll
2、使用VC自带工具depends打开这个动态链接库
不能用copy,copy的结果是字符串
而ord要求参数为char
Edit1.Text:=Edit1.Text+char(ord(pass[i])-1);
这样就OK
你的程序代码如下
var
i:Integer;
begin
for i:=1 to length(edit3.text) do
begin
Edit1.Text:=Edit1.Text+char(ord(edit3.Text[i])-1);
end;
end;
一 、引 言 由于Windows为微机提供了前所未有的标准用户界面、图形处理能力和简单灵便的操作,绝大多数程序编制人员都已转向或正在转向Windows编程。在许多用户设计的实际应用系统的编程任务中,常常要实现软件对硬件资源和内存资源的访问,例如端口I/O、DMA、中断、直接内存访问等等 。若是编制DOS程序,这是轻而易举的事情,但要是编制Windows程序,尤其是WindowsNT环境下的程序,就会显得较困难。 因为Windows具有"与设备无关"的特性,不提倡与机器底层的东西打交道,如果直接用Windows的 API函数或I/O读写指令进行访问和操作,程序运行时往往就会产生保护模式错误甚至死机,更严重的情况会导致系统崩溃。那么在Windows下怎样方便地解决上述问题呢?用DLL(Dynamic Link Libraries)技术就是良好途径之一。 DLL是Windows最重要的组成要素,Windows中的许多新功能、新特性都是通过DLL来实现的,因此掌握它、应用它是非常重要的。其实Windows本身就是由许多的DLL组成的,它最基本的三大组成模块Kernel、GDI和User 都是DLL,它所有的库模块也都设计成DLL。凡是以.DLL、.DRV、.FON、.SYS和许多以.EXE为扩展名的系统文件都是DLL,要是打开WindowsSystem目录,就可以看到许多的DLL模块。尽管DLL在Ring3优先级下运行,仍是实现硬件接口的简便途径。DLL可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式,减少了编程设计上的不便;同时,一个DLL在内存中只有一个实例,使之能高效经济地使用内存;DLL实现的代码封装性,使得程序简洁明晰;此外还有一个最大的特点,即DLL的编制与具体的编程语言及编译器无关,只要遵守DLL的开发规范和编程策略,并安排正确的调用接口,不管用何种编程语言编制的DLL都具有通用性。例如在BC31中编制的DLL程序,可用于BC、VC、VB、Delphi等多种语言环境中。笔者在BC31环境下编译了Windows下直接内存访问和端口I/O两个DLL,用在多个自制系统的应用软件中, 运行良好。
二、DLL的建立和调用 DLL的建立及调用方法在许多资料上有详细的介绍,为了节省篇幅,在这里仅作一些 主要的概括。
1.DLL的建立 关于DLL的建立,有如下几个方面的要素是不可缺少和必须掌握的: ?. 入口函数LibMain( ) 就象C程序中的WinMain( )一样,Windows每次加载DLL时都要执行LibMain( )函数,主要用来进行一些初始化工作。通常的形式是: int FAR PASCAL LibMain(HINSTANCE hInstance,WORD wDataSeg,WORD wHeapSize,LPSTR lpszCmdLine) { if(wHeapSize!=0) //使局部堆、数据段可移动 UnlockData(0); //解锁数据段 /*此处可进行一些用户必要的初始化工作*/ return 1; //初始化成功 } ?出口函数WEP( ) Windows从内存中卸载DLL时,调用相应的出口函数WEP( ),主要做一些清理工作,如释放占用的内存资源;丢弃某些字串、位图等资源;关闭打开的文件等等。 ?自定义的输出函数 为了让位于不同内存段的应用程序进行远程调用,自定义的输出函数必须定义为远程函数(使用FAR关键字),以防使用近程指针而得到意外的结果;同时,加上PASCAL关键字可加快程序的运行速度,使代码简单高效,提高程序的运行速度。 ?输出函数的引出方法 ? 在DLL的模块定义文件中(.DEF)由EXPORTS语句对输出函数逐一列出。例如: EXPORTS WEP @1 residentname //residentname可提高DLL效率和处理速度 PortIn @2 PortOut @3 //通常对所有输出函数附加系列号 ? 在每个输出函数定义的说明中使用_export关键字来对其引出。 以上两种方法任选其中的一种即可,不可重复。后面的两个实例分别使用了上述两种不同的引出方式,请留意。
2.DLL的调用 加载DLL时,Windows寻找相应DLL的次序如下: ?.当前工作盘。 ?Windows目录;GetWindowsDirectory( )函数可提供该目录的路径名。 ?Windows系统目录,即System子目录;调用GetSystemDiretory( )函数可获得这个目录的路径名。 ?DOS的PATH命令中罗列的所有目录。 ?网络中映象的目录列表中的全部目录。 DLL模块中输出函数的调用方法: 不论使用何种语言对编译好的DLL进行调用时,基本上都有两种调用方式,即静态调用方式和动态调用方式。静态调用方式由编译系统完成对DLL的加载和应用程序结束时DLL卸载的编码(如还有其它程序使用该DLL,则Windows对DLL的应用记录减1,直到所有相关程序都结束对该DLL的使用时才释放它),简单实用,但不够灵活,只能满足一般要求。动态调用方式是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,使用上较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。具体来说,可用如下的方法调用: ?.在应用程序模块定义文件中,用IMPORTS语句列出所要调用DLL的函数名。如: IMPORTS MEMORYDLL.MemoryRead MEMORYDLL.MemoryWrite ?让应用程序运行时与DLL模块动态链接 先用LoadLibrary加载DLL,再用GetProcAddress函数检取其输出函数的地址,获得其指针来调用。如: HANDLE hLibrary; FARPROC lpFunc; int PortValue; M hLibrary=LoadLibrary("PORTDLL.DLL"); //加载DLL if(hLibrary>31) //加载成功 { lpFunc=GetProcAddress(hLibrary,"PortIn"); //检取PortIn函数地址 if(lpFunc!=(FARPROC)NULL) //检取成功则调用 PortValue=(*lpFunc)(port); //读port端口的值 FreeLibrary(hLibrary); //释放占用的内存 } M
三、DLL应用实例源程序 1.直接内存访问的DLL源代码 //.DEF文件 LIBRARY MEMORYDLL DESCRIPTION 'DLL FOR MEMORY_READ_WRITE ' EXETYPE WINDOWS CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE SINGLE HEAPSIZE 1024 //DLL无自己的堆栈,故没有STACKSIZE语句 EXPORTS WEP @1 residentname ReadMemory @2 WriteMemory @3 //.CPP文件 #include
int FAR PASCAL LibMain(HINSTANCE hInstance,WORD wDataSeg,WORD wHeapSize,LPSTR lpszCmdLine)
{ if(wHeapSize!=0) UnlockData(0);
return 1;
}
int FAR PASCAL MemoryRead(unsigned int DosSeg,unsigned int DosOffset)
{ WORD wDataSelector,wSelector;
char far *pData; char value;
wDataSelector=HIWORD((DWORD)(WORD FAR *)&wDataSelector);
wSelector=AllocSelector(wDataSelector); //分配选择器
SetSelectorLimit(wSelector,0x2000); //置存取界限
SetSelectorBase(wSelector,(((DWORD)DosSeg)<<4)+(DWORD)DosOffset); //置基地址
pData=(char far *)((DWORD)wSelector<<16);
value=*pData; FreeSelector(wSelector); //释放选择器
return (value);
}
void FAR PASCAL MemoryWrite(unsigned int DosSeg,unsigned int DosOffset,char Data)
{
WORD wDataSelector,wSelector; char far *pData; wDataSelector=HIWORD((DWORD)(WORD FAR *)&wDataSelector); wSelector=AllocSelector(wDataSelector);
SetSelectorLimit(wSelector,0x2000);
SetSelectorBase(wSelector,(((DWORD)DosSeg)<<4)+(DWORD)DosOffset);
pData=(char far *)((DWORD)wSelector<<16); *pData=Data; FreeSelector(wSelector);
}
int FAR PASCAL WEP(int nParam) { return 1; }
2.端口读写I/O的DLL源代码 //.DEF文件 LIBRARY PORTDLL DESCRIPTION 'DLL FOR PORT_IN_OUT ' EXETYPE WINDOWS CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE SINGLE HEAPSIZE 1024 //.CPP文件 #include
#include
int FAR PASCAL LibMain(HINSTANCE hInstance,WORD wDataSeg,WORD wHeapSize,LPSTR lpszCmdLine)
{
if(wHeapSize!=0) UnlockData(0);
return 1;
}
int FAR PASCAL _export PortOut(int port,unsigned char value)
{
outp(port,value);
return 1;
}
int FAR PASCAL _export PortIn(int port)
{
int result;
result=inp(port);
return (result);
}
int FAR PASCAL _export WEP(int nParam) { return 1; }
分别将上面两个实例的.DEF文件和.CPP文件各自组成一个.PRJ文件,并进行编译链接成.EXE或.DLL文件就可以在应用程序中对其进行调用。
四、结 束 语 在上面,我们利用DLL技术方便地实现了Windows环境下对内存的直接访问和端口I/O的访问,仿效这两个例子,还可以编制出更多的适合自己应用系统所需的DLL,如用于数据采集卡的端口操作及扩展内存区访问、视频区缓冲区及BIOS数据区操作等许多实际应用的编程任务中。必要时只需直接更新DLL,而用不着对应用程序本身作任何改动就可以对应用程序的功能和用户接口作较大的改善,实现版本升级。因此,掌握好DLL技术对Windows程序开发者很有裨益。
勾孔西比: 关于特定情况下的调用,比如DLL函数中使用到了win32 API或者将C++生成的DLL供标准C语言使用,则需要注意以下一些情况: 如果使用到了win32 API,则应该使用调用方式为“__stdcall”. 在将C++生成的DLL供标准C语言使用...
开江县18980912799: VC2010 C++ 如何编写一个 简单的DLL(动态链接库) C++大牛 请进 - ?
勾孔西比: 下面示范一下用VS2010编写纯DLL,就是非ATL,MFC.第一步:新建工程->选择WIN32->WIN32 项目->选择DLL,并且把下面的 空项目 勾选上 第二步:再新建一个.cpp文件 里面编写你的Dll具体内容 第三步:编写一个.def主要用来解决编码问题 好了,这就基本上是完成了Dll编写了.如果说的太详细了,我怕这页面容不下额.我以前写过这方面的文章,你可以去参看一下:钩子编程(HOOK) 屏蔽所有按键鼠标及系统功能键:http://blog.csdn.net/qingdujun/article/details/25861615
开江县18980912799: 如何用VC++用C语言做DLL文件 - ?
勾孔西比: 新建->工程->dll(不要选MFC的那个)->一个简单的dll工程 看一下人家的,然后好好理解一下 dll是什么东东,工作原理是什么,知道一些API函数就可以自己写了
开江县18980912799: 将一个c++方法编译为dll文件 - ?
勾孔西比: 文件->新建->项目Visual C++ -> Win32 -> Win32项目下一步->DLL->完成将自己要导出的函数代码写入,并加上__declspec(dllexport)修饰添加.def文件,写入EXPORTS 你的函数名编译链接大功告成
开江县18980912799: 如何编译64位dll程序,有几种情况,在32位XP上用VC++6.0或者VS2010该怎么编译64位的dll. - ?
勾孔西比: 在64位的操作系统上用vs软件编译的dll默认就是64位.在32位XP上用VC++6.0编译64位的dll,需要安装sdk(最新版本是sdk2003),在开始菜单——sdk——open build environment window——windows server 2003 64-bit build environment—...
开江县18980912799: 在C++中如何编辑一个DLL?
勾孔西比: 估计你是说windows平台吧.用VC6的话,首先建立一个DLL工程,然后定义一个fac函数.int fac(int n){...}在.def文件中加上一行:fac @1编译就可以得到dll了.使用的话,typedef int (*fac)(int n);HANDLE h = LoadLibrary("fac.dll")fac func = GetProcAddress(h,"fac");func(12);
开江县18980912799: 需要C++源码编译dll文件 - ?
勾孔西比: 1.新建一个VC++工程,选择类型为"WIN32 Dynamic-Link Library"类型;2.选择"An empty DLL project"类型,点完成;3.在"FileView"窗口中点右键,选择"Add Files to project...",将所有的CPP文件及H文件添加到工程.4.在工程中添加一个与工程名字相同的DEF文件,如,工程名叫:abc,则添加一个叫abc.def文件5.在文件中添加导出的接口信息(在网上自己搜一下DEF文件的写法)就OK了.
开江县18980912799: visual studio c++怎么调用dll文件 - ?
勾孔西比: 1、先引入dll的命名空间:using DLL的命名空间; 2、在所用的项目上右击|添加引用|项目|选择所引用的DLL即可.
开江县18980912799: 使用vc++6.0 如何编写dll - ?
勾孔西比: 资源简介一、前言 自从微软推出16位的Windows操作系统起,此后每种版本的Windows操作系统都非常依赖于动态链接库(DLL)中的函数和数据,实际上Windows操作系统中几乎所有的内容都由DLL以一种或另外一种形式代表着,例如显示...
开江县18980912799: 如何用VC.NET编写Dll - ?
勾孔西比: 你要在创建项目的时候选择“类库”类型的项目,具体的方法是在创建项目的时候选择Visual C++ \ CLR \ 类库.然后在自动生成的Class1类中添加方法即可,在生成的时候就会生成一个DLL文件,在VB.NET中引用这个DLL文件就可以使用Class1类以及它的方法.当然你也可以将Class1改成另一个名字.