dll传递string实现方法

delphi中dll传递string的实现方法:
dll项目uses第一个引用sharemem单元;
调用的项目uses第一个引用sharemem单元;
调用的单元uses第一个引用sharemem单元;
**************************************************************
delphi中dll传递string的实现方法:
dll项目uses第一个引用sharemem单元;
调用的项目uses第一个引用sharemem单元;
调用的单元uses第一个引用sharemem单元;
**************************************************************

最好是不要使用 string作Dll参数或返回值,用Pchar更好兼容非Delphi语言编程
Delphi写DLL要注意的问题
a. 参数和返回值为string、动态数组类型时,DLL和EXE都要把ShareMem作为.dpr工程的第一个单元引用。当然最好是不要使用 string、动态数组类型,可以改用PChar、数组指针类型,如果是混合语言编程使用的话,就一定不能用string、动态数组类型。这样做的原因是 DLL和EXE的内存管理器(MemoryManager)不是一个,而string、动态数组类型是通过引用计数由Delphi自动进行内存管理的,它 何时分配何时释放,我们不能显式的知道的,DLL分配而EXE释放的话,这样就出问题了。用ShareMem就是为了让它们统一使用一个内存管理器进行内 存分配释放。 关于DLL和EXE内存管理器不同这一点,非常重要! b.DLL和EXE的VCL类体系不是一个,它们各自有一套,因此,从EXE传递过去的对象,要在DLL中用is判断类型和as作类型转换,那都不能得到期望的结果。 如果是bpl,就不会有这个问题 c.DLL中应用ADO、窗体(模态、非模态、MDI子窗体)、线程等的一些相关问题与今天的主题关系不大,就不作多讲了。参考DLL的详细论述请参考《Windows核心编程》第19、20章。

对使用Delphi制作DLL复用文件的建议在公司里有一些需要制作DLL的场合,因为熟悉、方便和简易,大多数使用Delphi来制作。现在就这个主题提出一些个人建议。

尽 量使用标准DLL接口。指的是传递的参数类型及函数返回类型不能是Delphi特有的,比如string(AnsiString),以及动态数组和含有这 些类型成员的复合类型(如记录),也不能是包含有这些类型成员数据成员的对象类型,以避免可能的错误。如果使用了string类型或动态数组类型,且调用 方不是Delphi程序,则基本上会报错。如果调用方是Delphi但调用方或被调用方没有在工程文件的第一包含单元不是ShareMem,也可能会出 错。

如果调用方是Delphi应用程序,则可能可以使用不包含禁止类型(string, 动态数组)数据成员的对象作为参数或返回值,但也应尽量避免。

如果调用方与被调用方都是Delphi程序,而且要使用string或动态数组作参数,则双方工程文件的第一包含单元必须是ShareMem。(C++Builder程序的情况可能与此相同,不过没有测试过。)

如果调用方不是Delphi程序,则string、动态数组、包含string或动态数组的复合数据类型及类实例,都不能作为参数及返回值。

因此,为了提高DLL的复用范围,避免可能存在的错误,应当使用标准WIN32 API标准参数类型,以前使用string的变量,可以使用PChar(s)转换。动态数组则转换为指针类型(@array[0]),并加上数组的长度。

如果因为调用方与被调用方都是Delphi程序,为了编写方便,不想进行上述转换,则推荐使用运行时包的形式。运行时包可以保证动态分配数据的正确释放。这样因为其扩展名(.bpl),显出该文件仅限于Delphi/C++Builder使用(不象DLL)。

其 次,尽量避免使用overload的函数/过程作输出,如果同一操作有多个方式,则可以让函数/过程名有少许差别,类似于Delphi中的 FormatXXXX、CreateXXXX等函数及方法,如CreateByDefaultFile, CreateDefault。

最 后,作为DLL的提供者,应当提供直接编程的接口文件,如Delphi中的.pas或.dcu(最好是.pas,因为可以有注释)、C及C++中的.h 和.lib。而不是让使用者们自己创建。如果非要有overload的函数/过程,这一点显得特别重要。另外,作为Delphi应用,提供的.pas文件 可以是提前连接的(使用external指定DLL中的输出函数),也可以是后期连接的(使用LoadLibrary、 GetProcAddress),DLL提供者提供编程接口文件,既显得正式(或HiQoS),又有保障。

delphi DLL中如何传递string参数

  1. Function IntToBin(N:Int64;L:Byte):Pchar;stdcall;
  2. var
  3. i: Int64 ;
  4. j: Byte ;
  5. str1:string;
  6. begin
  7. Result:='';str1:='';
  8. i:= N ;
  9. for j:= to L do
  10. begin
  11. str1:=str1+Chr(i mod ); i:=i div ;
  12. end ;
  13. result:=Pchar(str1);//在应用程序中调用时返回值出错
  14. end;

原函数是

  1. Function IntToBin(N:Int64;L:Byte):String;
  2. var
  3. i: Int64 ;
  4. j: Byte ;
  5. str1:string;
  6. begin
  7. Result:='';str1:='';
  8. i:= N ;
  9. for j:= to L do
  10. begin
  11. str1:=str1+Chr(i mod ); i:=i div ;
  12. end ;
  13. result:=str1;
  14. end;

1.不用引用ShareMem

2.全部用shortstring类型

3.如果能够,尽量不要用string回传参数,可以用integer代替(事先协议)
PChar可以,你就

  1. var
  2. MyProc=procedure(str: pchar);stdCall //这样就行了

Delphi DLL 字符串传递例子

  1. library EN;
  2.  
  3. uses
  4. SysUtils,
  5. Classes,
  6. UnitFormEN in 'UnitFormEN.pas' {FormEN};
  7. {$R *.res}
  8.  
  9. function GetJobType(p: PChar): Boolean; stdcall;
  10. var
  11. str: string;
  12. begin
  13. str := '我们是中国人,我们爱自己的祖国.';
  14. StrCopy(p, PChar(str));
  15. Result := Length(p) > Length(str);
  16. end;
  17.  
  18. function GetRates(p: PChar): Boolean; stdcall;
  19. var
  20. str: string;
  21. begin
  22. str := '我爱北京天安门.';
  23. StrCopy(p, PChar(str));
  24. Result := Length(p) > Length(str);
  25. end;
  26.  
  27. exports
  28. GetJobType,
  29. GetRates,
  30. ShowFormEN;
  31.  
  32. begin
  33. end.

Dll中传送Pchar类型

  1. procedure GetMsg(ret:Integer;Msg:PChar);stdcall;
  2. begin
  3. StrPCopy(Msg,'OK');
  4. end;
  5. var
  6. P:Pchar;
  7. begin
  8. P:=stralloc();
  9. GetMsg(,P);
  10. showmessage(P);
  11. strdispose(P);
  12. end;

dll传进传出字符串

需要别人的封装的dll,我想把封装的函数做一个dll在pb中调用,写的dll函数中需要传入传出字符串,我是用的pchar
函数如下:

  1. function p_string(var s:pchar):pchar;stdcall;
  2. begin
  3. s := '';
  4. Result := s;
  5.  
  6. end;
  7.  
  8. exports p_string;

做好dll后,在delphi中调用没有问题,返回的值也是正确的,delphi调用如下

  1. unit csstring;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button1: TButton;
  12. procedure Button1Click(Sender: TObject);
  13. private
  14. { Private declarations }
  15. public
  16. { Public declarations }
  17. end;
  18.  
  19. var
  20. Form1: TForm1;
  21. function p_string(var s:pchar):pchar;stdcall;external 'hljms.dll';
  22. implementation
  23.  
  24. {$R *.dfm}
  25.  
  26. procedure TForm1.Button1Click(Sender: TObject);
  27. var a,b:pchar;
  28. begin
  29. b := p_string(a);
  30. showmessage(b+','+a);//返回b='123',a='123'
  31. end;
  32.  
  33. end.

我在pb中声明
function string p_string(ref string s) library 'hljms.dll'
调用如下
string s,ls_return
s = space(10)
ls_return = p_string(s)
messagebox('',s+','+ls_return)
返回是:ls_return = '123',s = '?? '
我该如何处理,传入的问题已经解决,由于pb中没有指针,pchar代表指针类型,传入字符串,使用指针取值即可!可传出的怎么处理?

这个问题实际还是 dll 中的导出函数在使用指针做参数的时候,谁来分配空间的问题。

通常的做法是,在exe中分配空间,然后将指针传递给dll导出的函数,在函数里使用空间,然后返回。

dll:

  1. function func1(buff: PChar; var bufflen: Cardinal): Cardinal; stdcall;
  2. begin
  3. strncpy(buff, 'this is a test!', bufflen);
  4. bufflen := strlen(buff);
  5. Result := bufflen;
  6. end;
  7.  
  8. exe:
  9.  
  10. var
  11. pbuff : PChar;
  12. len, ret : Cardinal;
  13. begin
  14. len := ;
  15. pbuff := AllocMem(len);
  16.  
  17. ret := func1(pbuff, len);
  18.  
  19. ShowMessage(pubff);
  20.  
  21. FreeMem(pbuff);
  22. end;

我不熟悉 pb,不知道 string 是怎样定义的数据类型。如果 pb 支持字符数组的话,可以用字符数组试试。

dll用Pchar返回数据的问题

  1. 因为有可能被其它语言调用,所以想用Pchar来返回一些值,现在dll函数定义如下:
  2. function ReadInfo(iPort:Integer;var SN,ID,No,PCode:Pchar):Pchar;stdcall;
  3.  
  4. 然后我用delphi写了个小程序调用,
  5. Retcode : PChar;
  6. iPort : integer;
  7. sn,ID,No,PCode:Pchar;
  8. begin
  9. iCommPort := cmbComm1.ItemIndex +;
  10. Retcode := ReadInfo_HF(iPort,SN,ID,No,PCode);
  11.  
  12. 这样调用取出来的Pchar的值不对,经常改变,这个dll应该如何定义呢,程序又改如何调用呢
  1. Retcode : String; // 必须改 PChar;
  2. tmpchar:pchar;
  3.  
  4. iPort : integer;
  5. sn,ID,No,PCode:Pchar;
  6. begin
  7. iCommPort := cmbComm1.ItemIndex +;
  8.  
  9. setlength(Retcode,);// 尽量大
  10. tmpchar:=@Retcode[];
  11. tmpchar := ReadCardInfo_HF(iPort,SN,ID,No,PCode);
  12. setlength(Retcode,pos(#,Retcode));

PChar 实际是是一个指针,最好是加个返回长度,返回长度是不定的,只有dll里面才能确定,应该怎么加呢?

  1. 其实你按照 wql 的方法就可以做了的.
  2. var
  3. Retcode : String;
  4. iPort : integer;
  5. sn,ID,No,PCode,tmpchar:Pchar;
  6. begin
  7. iCommPort := cmbComm1.ItemIndex +;
  8. GetMem(TmpChar,);
  9. // 设定好 sn,id,no,pcode 的值
  10. TmpChar:= ReadCardInfo_HF(iPort,SN,ID,No,PCode);
  11. Retcode:=StrPas(TmpChar);
  12. freemem(TmpChar,);
  13. end;
  1. Delphi例子:
  2. function Test_GetXML(
  3. const XML : PChar;
  4. const XMLLen : Integer
  5. ):Integer;stdcall;
  6. var
  7. s : string;
  8. l : integer;
  9. begin
  10. s := '..........................';//获取值
  11. Result := Length(s); //值长度
  12. l := Result;
  13. if xmllen < l then l := xmllen; //处理分配长度不够的情况
  14. ZeroMemory(XML, XMLLen);
  15. CopyMemory(XML, @s[], l); //写入调用者分配的内存
  16. end;
  17.  
  18. C#调用声明:
  19. public class Dll_Test
  20. {
  21. private const string Dll_FileName = @"D:\Test.dll";
  22. [DllImport(Dll_FileName)]
  23. public static extern int Test_GetXML(
  24. StringBuilder XML, //输出参数,XML文档内容,请分配足够的空间
  25. int XMLLen //上面分配空间大小
  26. ); //返回XML文档大小
  27. }
  28. C#调用:
  29. StringBuilder s = new StringBuilder();
  30. Dll_Test.Test_GetXML(
  31. s,
  32. s.Capacity
  33. );
  34. textbox.Text = s.ToString();
  35.  
  36. 内存管理原则:谁分配的空间谁释放
  37. 你返回PChar的话,是DLL分配的内存,应该DLL释放,而调用者不知道DLL什么时候会释放,容易出错,特别在跨语言调用的情况下
  38. 所以参考WINAPI的约定写代码就行了
  1. //DLL
  2. function ReadInfo(iPort:Integer;SN,ID,No,PCode:Pchar):integer;stdcall;
  3. begin
  4. StrCopy (SN,PChar(''));
  5. StrCopy(ID,PChar(''));
  6. StrCopy(No,PChar(''));
  7. end;
  8.  
  9. //调用
  10. var
  11. //使用静态分配内存的方式
  12. vSN,vID,vNo:array[..] of char;//视具体情况分配内存
  13. begin
  14. FillChar(vSN,,#);
  15. FillChar(vID,,#);
  16. FillChar(vNo,,#);
  17. ReadInfo(,vSN,vID,vNo);//vSN,vID,vNo就可以得到返回值了
  18. end;
  19. 或者 用动态分配内存的方式
  20. var
  21. vSN,vID,vNo:PChar;
  22. begin
  23. GetMem(vSN,);
  24. GetMem(vID,);
  25. GetMem(vNo,);
  26. ReadInfo(,vSN,vID,vNo);//vSN,vID,vNo就可以得到返回值了
  27. FreeMem(vSN);
  28. FreeMem(vID);
  29. FreeMem(vNo);
  30. end;
  1. function ReadInfo(iPort:Integer; SN,ID,No,PCode:Pchar):Pchar;stdcall;
  2. 或者可以使用
  3. function ReadInfo(iPort:Integer;SN,ID,No,PCode:WideString):WideString;stdcall;
  4. 由于返回值都是指针类型的数据。
  5. 只要传入的数据指针不为空,而且大小符合,就没有问题。
  6. 建议使用WideString,因为PChar在别的语言里调用有时候会有问题,而WideStringWindows的标准数据类型。
  1. 要分两种情况,主要是看谁分配内存。
  2.  
  3. 第一种情况,DLL分配内存。这是针对 zhhg975 同学的。
  4. 函数定义不用改变,下面这样就可以,要改变的是它的实现
  5. function ReadInfo(iPort:Integer;var SN,ID,No,PCode:Pchar):Pchar;stdcall;
  6. begin
  7. //1 分别分配内存
  8. //2 将分配的内存分别赋给SN,ID,No,PCode
  9. //如 sn := pchar(AllocMem(Size));
  10. //返回值也一样 result := pchar(AllocMem(Size));
  11. //当然对SN[x]的赋值是必须的,否则总变化
  12. end;
  13.  
  14. 第二种情况,调用程序分配内存,这时DLL中直接使用就可以了,不用再分配了。
  15. 注意,最好把关键字var去掉。当然返回值还是要分配内存的
  16. function ReadInfo(iPort:Integer;SN,ID,No,PCode:Pchar):Pchar;stdcall;
  17. begin
  18. //sn[x] := ....;
  19. //result := pchar(AllocMem(Size));
  20. //...
  21. end;
  22.  
  23. 按照个人的用途可选用不同的内存分配函数。

Delphi调用Dll动态链接库,参数问题

我有个C++写的动态链接库,导出方式用extern "C" CString _declspec(dllexport)funname
在Delphi中调用时,当我像函数传入参数时就会报错,后来发现Dll中函数参数类型为CString的
请问:在Delphi中对应VC++的CString的是什么?PChar我也试过了,不行
但Dll中有些函数的返回值也是用CString的,我直接可以用showmessage弹出信息,不会报错,
以上,请帮忙解决
d中没有对应cstring的类,pchar不行,pchar是d的基本类型,c++在dll中使用cstring作为参数或返回值并不合适,需要做特殊的处理,可以考虑使用char*或lpstr替代
DELPHI代码一般都用pchar交互,并且用stdcall作参数传递约定
C++的DLL要用char*作参数
如果C++的dll你能修改,那就改成Char*吧,如果你改不了,那么,因为CString是VC特有的数据类型,所以Delphi无法与之交互。

就像如果Delphi导出一个返回值是TStringList的函数,C++没法接收一样。

例如:

  1. SendRcv2: function(cBegin: Pchar; SendMess: Pchar; ReturnMess: Pchar): PChar; stdcall;
  2. RMess := Sendrcv2('', Pchar(Value), pchar(sReturnStr));
  3.  
  4. 。。。。。。
  5.  
  6. constructor TShy.Create(Value, sfdm: string);
  7. var h: Integer;
  8. begin
  9. inherited create;
  10. h := LoadLibrary('SendRcv2.dll');
  11. if h <> then begin
  12. @SendRcv2 := GetProcAddress(h, 'SendRcv2');
  13. if @SendRcv2 = nil then begin
  14. // error
  15. end;
  16. end
  17. else begin
  18. // error
  19. end;
  20. end;

修改了下C++ 用char*代替了

delphi 将Dll等生成资源文件

资源文件一般为扩展名为res的文件,其自带的资源编译工具BRCC32.EXE(位于/Delphi/BIN目录下)

1.编写rc脚本文本
用记事本或其它文本编辑器编写一个扩展名为rc的文件,格式分别为在资源文件中的名称->类型->实际文件名称。

例如:要将文件名 demo.Dll的文件打包成一个资源文件,首先 新建一个文本文档,输入内容
mydemoDll RCDATA demo.DLL

mydemoDll 和 RCDATA 你可以随便写,这个是为了在使用资源时定义的名称和类型你也可以写成:a b demo.DLL
将文本保存,保存后将文本的后缀(.txt)改成(.rc)

2.将rc文件编译成res资源文件
将脚本文件和实际文件拷到Brcc32.EXE所在目录,执行DOS命令。格式为:Brcc32 脚本文件(回车),
例如:
将上面的Mydll.rc和demo.Dll拷到Brcc32.EXE所在目录,执行 Brcc32 Mydll.rc(回车)即可。如果编译成功,则会生成一个Mydll.res的文件,这个文件就是我们需要的资源文件。
3.在Delphi单元中加入资源文件
将生成的res资源文件拷贝到你所编程序的路径下,在单元文件{$R *DFM}后加上一句{$R Mydll.res},则将res文件加入去,编译后资 源文件即已包含在可执行文件中了。若你有多个资源文件,也按上法依次加入。/
4.在Delphi程序中调用资源文件(也可以在EXE中运行资源文件,如在EXE中直接运行另外一个EXE,或者调用DLL等,篇幅原因就不写了)

//D7下编辑

  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button1: TButton;
  12. procedure Button1Click(Sender: TObject);
  13. private
  14. { Private declarations }
  15. public
  16. { Public declarations }
  17. end;
  18.  
  19. var
  20. Form1: TForm1;
  21.  
  22. implementation
  23.  
  24. {$R *.dfm}
  25. {$R mydll.RES}
  26. //释放资源文件到指定文件夹,参数1:资源名称 参数2 资源类型,参数3:存放目录
  27. function ExtractRes(ResName,ResType, ResNewName: string): boolean;
  28. var
  29. Res: TResourceStream;
  30. begin
  31. try
  32. Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
  33. try
  34. Res.SavetoFile(ResNewName);
  35. Result := true;
  36. finally
  37. Res.Free;
  38. end;
  39. except
  40. Result := false;
  41. end;
  42. end;
  43.  
  44. procedure TForm1.Button1Click(Sender: TObject);
  45. begin
  46. ExtractRes('mydemoDll','RCDATA','d:/aaa.dll');
  47. end;

调用dll窗体

1.首先用delphi建一个dll工程:

  1. library Project2;
  2.  
  3. uses
  4. SysUtils,
  5. Classes,
  6. Unit1 in 'Unit1.pas' {Form1}; //dll中的窗体为Form1
  7. procedure ShowTest();stdcall; //dll函数 用于显示窗体
  8. var
  9. f:TForm1;
  10.  
  11. begin
  12. f:=TForm1.Create(nil);
  13. try
  14. f.ShowModal;
  15. finally
  16. f.Free;
  17. end;
  18. end;
  19.  
  20. {$R *.res}
  21. exports
  22. ShowTest; //外部调用函数
  23. begin
  24.  
  25. end.

2.新建Form1窗体,窗体为空窗体--》Unit1.pas。

  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.  
  7. Windows, SysUtils, Controls, Forms;
  8.  
  9. type
  10.  
  11. TForm1 = class(TForm)
  12.  
  13. private
  14.  
  15. { Private declarations }
  16.  
  17. public
  18.  
  19. { Public declarations }
  20.  
  21. end;
  22.  
  23. var
  24.  
  25. Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.dfm}
  30.  
  31. end.

3. CTRL+F9编译dll。 编译成功,并生成Project2.dll

4.新建工程,Project1. 采用动态调用dll方式:

  1. unit Unit_main;
  2.  
  3. interface
  4.  
  5. uses
  6.  
  7. Windows, SysUtils, Classes, Controls, Forms, StdCtrls;
  8.  
  9. type
  10.  
  11. TForm1 = class(TForm)
  12.  
  13. Button1: TButton;
  14.  
  15. procedure Button1Click(Sender: TObject);
  16.  
  17. private
  18.  
  19. { Private declarations }
  20.  
  21. public
  22.  
  23. { Public declarations }
  24.  
  25. end;
  26.  
  27. var
  28. Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.dfm}
  33.  
  34. procedure TForm1.Button1Click(Sender: TObject);
  35.  
  36. type
  37.  
  38. mypointer=Procedure();stdcall;
  39.  
  40. var
  41. Handle:THandle;
  42. frm_p:mypointer;
  43. begin
  44. Handle:=loadlibrary('Project2.dll');
  45. if Handle> then
  46. begin
  47. frm_p:=GetProcAddress(Handle,'ShowTest');
  48. if @frm_p<>nil then frm_p;
  49. end;
  50. Freelibrary(Handle);
  51. end;
  52.  
  53. end.

5. 修改Project1.dpr文件,加上Sharemem:
Sharemem已经说的很清楚了,如果的导出函数中参数或返回值有string类型,那么就需要引用ShareMem
至于你dll内部使用string类型跟引不引用ShareMem没关系,ShareMem只是解决dll中直接与外界
发生交互的string变量内存管理问题,比如何时释放啊该不该释放

  1. uses
  2. Sharemem ,Forms,
  3. Unit_main in 'Unit_main.pas' {Form1};

6. 运行Project1,点击Button1,实现调用出dll窗体。

 Delphi中DLL的其他应用

1.DLL的入口函数和出口函数

  1. 在编写DLL时可以在DLL项目文件的begin..end之间加入DLL的进入口函数和出口函数,全局变量DLLProc是一个过程指针,指定入口/出口函数,初始值为nil,只需将自己的出入口函数赋值给它即可,自己的出入口函数必须传入一个DWord类型的参数。一下是出入口函数事件对应的用途。
  2. DLL_PROCESS_ATTACH 在进程启动或调用LoadLibrary( )时,DLL映射到当前进程的地址空间。在这个事件期间,D L L初始化实例数据
  3. DLL_PROCESS_DETACH DLL正从进程的地址空间分离出来,这也许是进程本身退出或调用了FreeLibrary( )。在该事件里,D L L也许没有初始化任何实例。
  4. DLL_THREAD_ATTACH 进程创建了一个新线程。这时,系统会调用所有和这个进程相关联的DLL入口函数。这个调用在新线程的环境中进行,用于分配线程特定的数据
  5. DLL_THREAD_DETACH 一个线程正在退出。在该事件里,DLL将释放线程特定的初始化数据
  6. 警告 调用TerminateThread()非正常终止线程时,没有调用DLL_THREAD_DETACH

2.DLL中使用回调函数
回调函数一般被Win32DLL或其他DLL调用,而不是由应用程序调用。当调用回调函数时传递函数的地址。在DLL可以定义一种回调函数类型,然后将其做为导出函数的参数,实际应用程序调用DLL时需自己实现该回调函数类型,并传递实际类型参数。

案例一。
打开delphi新建一个dll,源码如下:

  1. library DLLEntry;
  2. uses
  3. SysUtils,
  4. Windows,
  5. Dialogs,
  6. Classes;
  7. {$R *.res}
  8. procedure DLLEntryPoint(dwReason:DWord); //入出口函数
  9. begin
  10. case dwReason of
  11. DLL_Process_Attach:showmessage('Attaching to process');
  12. DLL_PROCESS_DETACH:Showmessage('Detaching from process');
  13. DLL_THREAD_ATTACH:MessageBeep();
  14. DLL_THREAD_DETACH:MessageBeep();
  15. end;
  16. end;
  17. begin
  18. DllProc:=@DLLEntryPoint; //赋值给全局变量
  19. DLLEntryPoint(DLL_PROCESS_ATTACH); //传DWord类型值
  20. end.

调用dll,新建一个Delphi应用程序,在窗体上放置一个label和4个button控件。源码如下:

  1. unit mainFrm;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5. Dialogs, StdCtrls;
  6. type
  7. TTestThread=class(TThread) //定义线程
  8. procedure Execute;override;
  9. procedure SetCaptionData;
  10. end;
  11. TmainForm = class(TForm)
  12. btnLoadLib: TButton;
  13. btnFreeLib: TButton;
  14. btnCreateThread: TButton;
  15. btnFreeThread: TButton;
  16. lblCount: TLabel;
  17. procedure btnLoadLibClick(Sender: TObject);
  18. procedure btnFreeLibClick(Sender: TObject);
  19. procedure btnCreateThreadClick(Sender: TObject);
  20. procedure btnFreeThreadClick(Sender: TObject);
  21. procedure FormCreate(Sender: TObject);
  22. private
  23. LibHandle:THandle;
  24. TestThread:TTestThread;
  25. Counter:Integer;
  26. GoThread:Boolean;
  27. public
  28. { Public declarations }
  29. end;
  30. var
  31. mainForm: TmainForm;
  32. implementation
  33. {$R *.dfm}
  34. procedure TTestThread.Execute(); //重写线程的Execute方法
  35. begin
  36. while mainForm.GoThread do
  37. begin
  38. Synchronize(SetCaptionData);
  39. Inc(mainForm.Counter);
  40. end;
  41. end;
  42. procedure TTestThread.SetCaptionData; //线程的异步方法修改label控件的caption
  43. begin
  44. mainForm.lblCount.Caption:=IntToStr(mainForm.Counter);
  45. end;
  46. procedure TmainForm.btnLoadLibClick(Sender: TObject); //载入dll
  47. begin
  48. if LibHandle= then
  49. begin
  50. LibHandle:=LoadLibrary('DLLEntry.dll');
  51. if LibHandle= then
  52. raise Exception.Create('Unable to Load DLL');
  53. end
  54. else
  55. MessageDlg('Library already loaded',mtWarning,[mbOK],);
  56. end;
  57. procedure TmainForm.btnFreeLibClick(Sender: TObject); //释放dll
  58. begin
  59. if not (LibHandle=) then
  60. begin
  61. FreeLibrary(LibHandle);
  62. LibHandle:=;
  63. end;
  64. end;
  65. procedure TmainForm.btnCreateThreadClick(Sender: TObject); //开启线程
  66. begin
  67. if TestThread=nil then
  68. begin
  69. GoThread:=True;
  70. TestThread:=TTestThread.Create(False);
  71. end;
  72. end;
  73. procedure TmainForm.btnFreeThreadClick(Sender: TObject); //释放线程
  74. begin
  75. if Assigned(TestThread) then
  76. begin
  77. GoThread:=False;
  78. TestThread.Free;
  79. TestThread:=nil;
  80. Counter:=;
  81. end;
  82. end;
  83. procedure TmainForm.FormCreate(Sender: TObject); //初始化操作
  84. begin
  85. LibHandle:=;
  86. TestThread:=nil;
  87. end;
  88. end.

新建一个dll,源码如下:

  1. library StrSrchLib;
  2.  
  3. uses
  4. SysUtils,
  5. Windows;
  6. {$R *.res}
  7. type
  8. TFoundStrProc=procedure (StrPos:PChar);stdcall; //定义过程类型
  9. function SearchStr(ASrcStr,ASearchStr:PChar;AProc:TFarProc):Integer;stdcall; //字符串查找功能
  10. var
  11. FindStr:PChar;
  12. begin
  13. FindStr:=ASrcStr;
  14. FindStr:=StrPos(FindStr,ASearchStr); //查找ASearchStr在FindStr中出现位置
  15. while FindStr<>nil do
  16. begin
  17. if AProc<>nil then
  18. TFoundStrProc(AProc)(FindStr); //强制类型转换,将FindStr作为参数
  19. FindStr:=FindStr+;
  20. FindStr:=StrPos(FindStr,ASearchStr); //循环查找
  21. end;
  22. end;
  23. exports
  24. SearchStr;
  25. begin
  26. end.

新建Delphi应用程序,在窗体上放置一个edit 一个memo和一个button控件,源代码如下:

  1. unit CallTest;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5. Dialogs, StdCtrls;
  6. type
  7. TMainForm = class(TForm)
  8. btnCallDLLFunc: TButton;
  9. lblSrchWrd: TLabel;
  10. mmoStr: TMemo;
  11. edtSearchStr: TEdit;
  12. procedure btnCallDLLFuncClick(Sender: TObject);
  13. end;
  14. var
  15. MainForm: TMainForm;
  16. count:integer; //全局计数变量
  17. implementation
  18. {$R *.dfm}
  19. function SearchStr(ASrcStr,ASearchStr:PChar;AProc:TFarProc):Integer;stdcall;external 'StrSrchLib.dll'; //声明导入函数
  20. procedure StrPosProc(AStrPsn:PChar);stdcall; //具体的回调函数类型
  21. begin
  22. inc(count);
  23. end;
  24. procedure TMainForm.btnCallDLLFuncClick(Sender: TObject);
  25. var
  26. s,s2:string;
  27. begin
  28. count:=;
  29. SetLength(s,mmoStr.GetTextLen);
  30. mmoStr.GetTextBuf(PChar(s),mmoStr.GetTextLen); //这两句功能是将memo控件内容赋值给s字符串
  31. s2:=edtSearchStr.Text;
  32. SearchStr(PChar(s),PChar(s2),@StrPosProc);
  33. ShowMessageFmt('%s %s %d %s',[edtSearchStr.Text,'occurs',count,'times.']);
  34. end;
  35. end.

DLL还有其他许多功能,在此不在一一列举,源码参考了delphi5编程指南,在Delphi7下编译运行通过,关于DLL还需在项目中更多应用才可熟能生巧。

DLL文件的加载

最好把DLL文件放到Delphi安装目录下Lib或Imports下
1.Tool菜单下Library标签——>LibraryPathxx下,浏览找到DLL文件所在在文件夹(GDI+为例),

——>add,GUI+这个路径回显示到上面的对话框中,确定安装OK!
特别声明:GDI下的包不只是DLL文件还有一些GDIPAPI.dcu、GDIPAPI.das、GDIPOBJ.pas、

GDIPOBJ.dcu、GDIPUTIL.pas、DirectDraw.pas.DirectX.inc、Jedi.inc、DerectDraw.dcu
画圆就可以了:

  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button1: TButton;
  12. procedure Button1Click(Sender: TObject);
  13. private
  14. { Private declarations }
  15. public
  16. { Public declarations }
  17. end;
  18.  
  19. var
  20. Form1: TForm1;
  21.  
  22. implementation
  23. uses GDIPAPI,GDIPOBJ;
  24. {$R *.dfm}
  25.  
  26. procedure TForm1.Button1Click(Sender: TObject);
  27. var
  28. g: TGPGraphics;
  29. p: TGPPen;
  30. begin
  31. g := TGPGraphics.Create(Canvas.Handle);
  32.  
  33. p := TGPPen.Create(aclRed, );
  34. {参数1颜色; 参数2是笔宽, 笔宽是可选, 默认 1}
  35.  
  36. g.DrawEllipse(p, , , , );
  37.  
  38. p.Free;
  39. g.Free;
  40. end;
  41.  
  42. end.

dll函数

  1. type
  2. TDllFun = function (TestStr: PChar; Len: Integer): Integer;
  3.  
  4. procedure TForm1.Button2Click(Sender: TObject);
  5. var
  6. GetStr: TDllFun;
  7. Dllhandle: HMODULE;
  8. TestStr: PChar;
  9.  
  10. begin
  11. Dllhandle := LoadLibrary('Project2.dll');
  12. if Dllhandle <> then
  13. begin
  14. try
  15. GetStr := GetProcAddress(Dllhandle, 'GetStr');
  16.  
  17. GetMem(TestStr, ); //字符串长度,自己设置
  18.  
  19. GetStr(TestStr, );
  20. //使用
  21. ShowMessage(TestStr);
  22.  
  23. FreeMem(TestStr);
  24. finally
  25. FreeLibrary(Dllhandle);
  26. end;
  27. end;
  28. end;

delphi dll调用问题的更多相关文章

  1. 在.net中调用Delphi dll的Pchar转换

    Pchar是非托管代码,要在.net中调用Delphi dll中的功能,请使用MarshalAs属性告知.net调用PInvoke去转换.net中标准的string类型.如果Delphi dll是De ...

  2. Delphi动态调用C++写的DLL

    c++ DLL 文件,建议用最简单的c++编辑工具.不会加入很多无关的DLL文件.本人用codeblocks+mingw.不像 VS2010,DLL编译成功,调用的时候会提示缺其他DLL. 系统生成的 ...

  3. Delphi 7调用C语言编写的DLL

    DLL一定是要C语言导出的符号,也就是extern “C”. 当然,我们都知道DLL调用分为动态调用和静态调用. 动态调用的一般思想为,先LoadLibrary那个你想加载的DLL,然后通过GetPr ...

  4. Delphi Dll 动态调用例子(3)-仔细看一下

    http://blog.163.com/bxf_0011/blog/static/35420330200952075114318/ Delphi 动态链接库的动态和静态调用 为了让人能快速的理解 静态 ...

  5. Delphi Dll 动态调用例子(2)

    http://zhidao.baidu.com/question/157196792.html delphi动态调用DLL 写了个1.dll内容如下 library Project2; uses Sy ...

  6. C# 调用Delphi dll

    delphi dll 源码: library dllres; type char10 = ..] of char; TMydata = packed record id: Integer; name: ...

  7. Delphi程序调用C#.Net编译的DLL并打开窗体(详解)

    Delphi程序调用C#.Net编译的DLL并打开窗体(详解)最近用C#.Net写了一个公用模块, 本以为仅提供给.Net程序使用, 但是领导要求把这些功能提供给旧系统使用, 天啦, 几套旧系统全是D ...

  8. vb6如何调用delphi DLL中的函数并返回字符串?

    1,问题描述 最近发现vb6调用delphi DLL中的函数并返回字符串时出现问题,有时正常,有时出现?号,有时干脆导致VB程序退出 -- :: 将金额数字转化为可读的语音文字:1转化为1元 ???? ...

  9. delphi 跨版本DLL调用嵌入窗体实现

    delphi 能实现把别的DLL的窗体句柄查到后,贴到PANL之中,此类文章网上不少,而如果是delphi不同版本开发的DLL互调时,一些控件内部的定义有所区别,因为无法(至少目前我觉得理论上不可行) ...

随机推荐

  1. Oracle with as语法

    with as优点 增加了sql的易读性,如果构造了多个子查询,结构会更清晰: 更重要的是:“一次分析,多次使用”,这也是为什么会提供性能的地方,达到了“少读”的目标 用法:给查询的语句起个别名 e. ...

  2. shell正则匹配IP地址

    IP分成5大类: A类地址 ⑴ 第1字节为网络地址,其它3个字节为主机地址. ⑵ 范围:1.0.0.1—126.155.255.254 ⑶ 私有地址和保留地址: ① 10.X.X.X是私有地址(只能在 ...

  3. Android中的ImageView的getDrawableCache获取背景图片的时候注意的问题

    获取ImageView的背景图片使用getDrawableCache方法,不要使用getDrawable方法,后者获取不到图片的. 1.在调用imageView.getDrawableCache()之 ...

  4. Linux v4l2编程(摄像头信息采集)

    基于Linux3.4.2,自己做一点儿视频信息采集及网络传输的小实验,边做边学,一些基础知识同步整理..... 1. 定义 V4L2(Video For Linux Two) 是内核提供给应用程序访问 ...

  5. MySQL 时间戳与日期格式的相互转换(转)

    1.UNIX时间戳转换为日期用函数: FROM_UNIXTIME() select FROM_UNIXTIME(1156219870); 输出:2006-08-22 12:11:10 2.日期转换为U ...

  6. 软件-平面设计-CorelDRAW:CorelDRAW

    ylbtech-软件-平面设计-CorelDRAW:CorelDRAW CorelDRAW Graphics Suite是加拿大Corel公司的平面设计软件:该软件是Corel公司出品的矢量图形制作工 ...

  7. Mosaic

    Mosaic 是最古老的WEB浏览器,这是个套件FOR WINDOWS(包括TCP/IP,拨号,EMAIL等).

  8. NTFS文件系统

    一.Volume和Cluster 卷(Volume)和簇(Cluster)是NTFS用来描述物理磁盘的单位. 卷之间是相对独立的,卷的概念其实就是分区(Partition). 簇的引入是为了方便处理不 ...

  9. Gym 102082B : Arithmetic Progressions

    戳这里看题目吧! 题目大意:给你一个长度为n(2<=n<=5000)的序列,没有重复的数字,序列中每个元素满足(0<=numi<=1e9).求一个最长的数列满足差分值相同(除n ...

  10. Struct和Union的sizeof计算

    struct 结构体的大小不是简单的成员相加,要考虑存储空间的字节对齐 1.空结构体的大小为1 2.含有static的结构体在计算大小时不算上static变量,因为static存储在全局数据空间,而s ...