我要用Delphi写一个DLL,这个DLL要给VC编写的程序使用的,函数接口是
bool CheckFile(char *lpFileName);
那么根据这个接口如何在DLL中创建函数,函数的参数如何部分如何写,需要注意那些,我用以下方法,失败了
function FileHave(lFile:Pchar):boolean;各位高手请赐教
bool CheckFile(char *lpFileName);
那么根据这个接口如何在DLL中创建函数,函数的参数如何部分如何写,需要注意那些,我用以下方法,失败了
function FileHave(lFile:Pchar):boolean;各位高手请赐教
lFile的内存必须由外部程序自己管理。
2. boolean建议换成longbool;
3. 双方协商内存的分配负责问题,或说契约。
4. 不明白的就模仿Windows API的风格。
delphi中使用的pascal的调用方式(另外也使用的寄存器从而更快)
因此要和其它语言混合的话,应该使用WIN32API的调用方式stdcall
“0x00f511c3”指令引用的“0x04d76418”内存。该内存不能为“read”我的函数申明如下
function CheckFile(lFileName:pchar):longbool;stdcall;
The cdecl convention is useful when you call functions from DLLs written in C or C++ 个人认为必须为Cdecl方式调用
另外,你返回的pChar指针必须是线程安全的,因为你的DLL可能同时被几个程序调用 没试过,只给你参考!
不可能,为了实验,我的函数中就保留了Result:=False;来返回参数,没有其他语句to chngoing(gogo)
首先我用Cdecl方式调用调用也试过了,情况一样,至于你说的线程安全我不是很懂能详细说明吗???各位大哥我实在是想不出怎么解决了,大家帮帮忙啊
用Delphi来调用完全正常。
将函数改为BYTE CheckFile(char *lpFileName);就行了
不用加_stdcall关键字的,因为pascal函数调用方式本来就是_stdcall的
“不用加_stdcall关键字的,因为pascal函数调用方式本来就是_stdcall的
”
非也。
----------------
delphi默认调用方式是register调用而不是stdcall,stdcall(或者pascal, cdecl, safecall调用)必须显式说明。
----------------
调用方式倒并不一定要用cedcl or stdcall,只要两边协调就是了;
----------------
返回类型建议还是一律模仿windows API, 使用windows单元里的longbool与其它语言兼容,而避免使用system单元的boolean类型。
你说的“使用windows单元里的longbool与其它语言兼容,而避免使用system单元的boolean类型。”如何选择使用哪个单元中的东西,我怎么弄他都使用了system单元中的类型
在longbool前单元前缀,很多时候可以把单元名理解为一个类,:)
windows,
SysUtils,
Classes;
{$R *.res}
function CheckFile(lFileName:pchar):windows.longbool;stdcall;
//这行出现[Error] Project2.dpr(19): Undeclared identifier: 'longbool'错误,你的方法不行
begin
Result:=False
end;
exports
CheckFile;
begin
end.
我来反编译以下看看
大家在软件开发时经常会遇到这样的情况,在不同的开发环境中为实现一些功能相同的过程,由于开发所使用的设计语言不同,因而不得不编写许多类似的代码,甚至有时要在同一个开发环境不同项目中重写代码,这就造成了很大的资源浪费。动态链接库能较好的解决这个问题,重复利用代码将大大提高了开发效率。一般,用户在应用程序中基于如下要求创建和使用DLL:1. 在不同的可执行文件之间共享的程序;2. 在设计应用程序时,将其拆分成各个相互独立功能部件,为以后这些功能部件各自升级提供方便的途径。动态链接库将共享程序或功能部件做成库中的函数,形成DLL文件,其它应用程序通过使用DLL调用这些函数。在这里将对Delphi和VC中创建和使用动态链接库的方法做一介绍。Delphi和VC定义的动态链接库均可在两者的开发环境中使用。一、 用Delphi创建DLLDelphi的DLL创建并不复杂,下面向大家介绍Delphi的DLL创建方法。(1)首先创建一个新的DLL项目(NewProject)project1,文件头部为:library Project1; (2)USES语句后面加入ExPorts语句,指明调用DLL的函数名,形式为:exports checkpwd name 'checkpwd'; (3)在DLL的Pas文件中Type......End后加入该DLL的函数或过程的声明,形式如下:FunctionName(argment):Boolean;export; 该函数也可以存在于另一个pas文件中(如Unit1.pas),此时只需在项目文件中加入:uses Unit1 in 'Unit1.pas' {Form1}; 值得注意的是,该函数或过程应加入窗体的Create和Free(产生和释放)方法。(4)对项目进行编译即形成DLL文件,可被其它项目调用。二、Delphi中DLL的调用调用DLL有两种方法,一种是在应用程序装载时调用,另一种是在应用程序运行时调用。(1) 装载时调用DLL在调用DLL的Pas文件中,对DLL函数进行外部声明,声明应位于Implementation后,形式如下:Implementation Function functionname(argment):Boolean;far;External 'DllName'; 其中External关键字后面的引号内是DLL的文件名,该文件一般应放在系统的system目录下,或与调用它的项目同一目录。声明以后即可在Pas文件任何地方引用DLL函数。装载时调用DLL的优点是速度较快,程序间也可共享代码。(2) 运行时调用DLLDLL的另一种调用方法是在运行时调用。这种方法要调用到Windows的API函数LoadLibrary,GetProcAddress,FreeLibrary等。此方法主要用于调用其它语言,特别是C++编译的DLL。假定你欲调用的DLL中包括一个函数:Function checkpwd(pwd:string):boolean;export; 那么,首先在欲调用DLL的程序Type类型声明处加入一句:Type Tcheckpwd= function(pwd:string):boolean; 此句的作用如同C++中声明的函数指针。然后定义如下变量∶Var aptr:TFarproc; lhnd:THandle; flag:boolean; 其中Aptr,lhnd两变量声明必须有,flag是DLL函数返回值,视情况而定。在调用DLL处加入如下语句进行DLL装载:lhnd:=Loadlibrary('路径:DLL文件名');{如lhnd:=Loadlibrary('c:\project1.dll'); aptr:=GetprocAddress(lhnd,'checkpwd'); 下面可直接调用DLL了:flag:=Tcheckpwd(aptr)( 'pwd');{根据函数填相应的变量参数} 调用完以后,用FreeLibrary释放DLL占用的内存:FreeLibrary(lhnd);三、用VC创建DLL在VC中创建DLL,与Delphi中的创建过程相似,步骤如下:(1)新建一个DLL项目。MFC提供两种类型的动态链接库:常规型DLL、扩展型DLL。其中,常规型DLL适合于非MFC开发环境下采用支持DLL调用的程序设计语言开发的应用程序,扩展型DLL只能被MFC程序使用。(2)创建该DLL中的过程或函数,只需在程序中加入下列语句:extern "C" _declspec(dllexport) int yanzheng(CString input,char* zcm) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); file://具体实现过程 } 该函数的功能是验证注册码是否合法,其中yanzheng为函数名,int为函数返回值类型,()内为函数参数。编译通过后即可使用。四、 VC中DLL的调用在VC中调用动态链接库时,类似于Delphi中运行时调用DLL的方法。也要调用到Windows的API函数LoadLibrary,GetProcAddress等。此方法对于调用其它语言和VC编译的DLL均适用。假定DLL中包括一个函数:int yanzheng(CString input,char* zcm) 首先在欲调用DLL函数的cpp文件前部先声明函数指针,定义函数类型:typedef int (* _YANZHENG)(CString,char* zcm); 然后定义如下变量∶HINSTANCE hLibrary; _YANZHENG yanzheng; 在调用DLL处加入如下语句进行DLL装载: hLibrary=LoadLibrary("zcdll.dll"); yanzheng=(_YANZHENG)GetProcAddress(hLibrary,"yanzheng"); shuchu= (*yanzheng)(shuru,zcm); FreeLibrary(hLibrary); 五、 几点提示(1)如果用Delphi创建DLL时用到其它的form,则在DLL的输出函数中应包括form的create(创建)和free(释放),而且在显示该窗口时只能用showmodal过程,不能用show过程,在后面的例子中能详细看到。(2)如果Delphi创建的DLL中的函数或过程,用string类型作为参数输入或返回string类型,当用VC或其它程序调用时,经常会出错,反之亦然。为了解决这种情况,使不同程序之间在使用字符串类型时,接口更安全,建议使用pchar类型,而不是string类型。而且要在程序中加入内存管理,使用系统提供的sharemem单元。下面是一个实现将星期标识由数字转换成英文的例子:uses sharemem; exports makeitaday; var mydate:pchar; function makeitaday(S:integer):pchar;stdcall;export; implementation function makeitaday(S:integer):pchar;stdcall;export; var thedate:array[0..20] of char; begin GetMem(mydate, 200); if s=1 then thedate:='Sunday '; file://………. strpcopy(mydate,thedate); makeitaday:=mydate; end; 六、实例因为用Delphi创建和调用DLL,过程与用VC创建和调用DLL相似,只是前者代码要比在VC环境中稍微复杂一些,因此在文章的最后给出一个完整的用Delphi创建和调用DLL的例子。该DLL主要用来检查输入的口令是否正确,窗体含有一个Edit编辑框,一个按钮Button,在编辑框内输入口令,比较编辑框的值和输入参数返回真假值。//文件名为checkpassword.dpr;编译此文件生成checkpassword.dll library checkpassword; uses SysUtils, Classes, Unit1 in 'Unit1.pas' {Form1}; exports checkpwd name 'checkpwd';//声明DLL函数 {$R *.RES} begin end.file://文件名为unit1.pas unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) password: TEdit; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; flag:boolean;//返回输入密码是否正确 rightpwd:string;//记录输入参数(正确的密码) function checkpwd(pwd:string):boolean;export;//声明DLL函数 implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); begin if password.text=rightpwd then flag:=true; form1.close; end;function checkpwd(pwd:string):boolean;export; begin flag:=false; rightpwd:=pwd;//读入正确的密码值 form1:=Tform1.create(Application);//创建密码验证窗口 form1.ShowModal;//显示窗口 checkpwd:=flag; form1.free;//释放资源 end; end.file://主程序main.pas,调用DLL unit main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) jieguo: TEdit; Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation function checkpwd(pwd:string):boolean;external 'project1.dll' ;//函数说明 {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); begin if checkpwd('congrong') then//调用函数 jieguo.text:='true' else jieguo.text:='false'; end; end. 以上程序在Windows98/Delphi5下编译通过。