delphi dll调用问题
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参数
- Function IntToBin(N:Int64;L:Byte):Pchar;stdcall;
- var
- i: Int64 ;
- j: Byte ;
- str1:string;
- begin
- Result:='';str1:='';
- i:= N ;
- for j:= to L do
- begin
- str1:=str1+Chr(i mod ); i:=i div ;
- end ;
- result:=Pchar(str1);//在应用程序中调用时返回值出错
- end;
原函数是
- Function IntToBin(N:Int64;L:Byte):String;
- var
- i: Int64 ;
- j: Byte ;
- str1:string;
- begin
- Result:='';str1:='';
- i:= N ;
- for j:= to L do
- begin
- str1:=str1+Chr(i mod ); i:=i div ;
- end ;
- result:=str1;
- end;
1.不用引用ShareMem
2.全部用shortstring类型
3.如果能够,尽量不要用string回传参数,可以用integer代替(事先协议)
PChar可以,你就
- var
- MyProc=procedure(str: pchar);stdCall; //这样就行了
Delphi DLL 字符串传递例子
- library EN;
- uses
- SysUtils,
- Classes,
- UnitFormEN in 'UnitFormEN.pas' {FormEN};
- {$R *.res}
- function GetJobType(p: PChar): Boolean; stdcall;
- var
- str: string;
- begin
- str := '我们是中国人,我们爱自己的祖国.';
- StrCopy(p, PChar(str));
- Result := Length(p) > Length(str);
- end;
- function GetRates(p: PChar): Boolean; stdcall;
- var
- str: string;
- begin
- str := '我爱北京天安门.';
- StrCopy(p, PChar(str));
- Result := Length(p) > Length(str);
- end;
- exports
- GetJobType,
- GetRates,
- ShowFormEN;
- begin
- end.
Dll中传送Pchar类型
- procedure GetMsg(ret:Integer;Msg:PChar);stdcall;
- begin
- StrPCopy(Msg,'OK');
- end;
- var
- P:Pchar;
- begin
- P:=stralloc();
- GetMsg(,P);
- showmessage(P);
- strdispose(P);
- end;
dll传进传出字符串
需要别人的封装的dll,我想把封装的函数做一个dll在pb中调用,写的dll函数中需要传入传出字符串,我是用的pchar
函数如下:
- function p_string(var s:pchar):pchar;stdcall;
- begin
- s := '';
- Result := s;
- end;
- exports p_string;
做好dll后,在delphi中调用没有问题,返回的值也是正确的,delphi调用如下
- unit csstring;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm1 = class(TForm)
- Button1: TButton;
- procedure Button1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1: TForm1;
- function p_string(var s:pchar):pchar;stdcall;external 'hljms.dll';
- implementation
- {$R *.dfm}
- procedure TForm1.Button1Click(Sender: TObject);
- var a,b:pchar;
- begin
- b := p_string(a);
- showmessage(b+','+a);//返回b='123',a='123'
- end;
- 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:
- function func1(buff: PChar; var bufflen: Cardinal): Cardinal; stdcall;
- begin
- strncpy(buff, 'this is a test!', bufflen);
- bufflen := strlen(buff);
- Result := bufflen;
- end;
- exe:
- var
- pbuff : PChar;
- len, ret : Cardinal;
- begin
- len := ;
- pbuff := AllocMem(len);
- ret := func1(pbuff, len);
- ShowMessage(pubff);
- FreeMem(pbuff);
- end;
我不熟悉 pb,不知道 string 是怎样定义的数据类型。如果 pb 支持字符数组的话,可以用字符数组试试。
dll用Pchar返回数据的问题
- 因为有可能被其它语言调用,所以想用Pchar来返回一些值,现在dll函数定义如下:
- function ReadInfo(iPort:Integer;var SN,ID,No,PCode:Pchar):Pchar;stdcall;
- 然后我用delphi写了个小程序调用,
- Retcode : PChar;
- iPort : integer;
- sn,ID,No,PCode:Pchar;
- begin
- iCommPort := cmbComm1.ItemIndex +;
- Retcode := ReadInfo_HF(iPort,SN,ID,No,PCode);
- 这样调用取出来的Pchar的值不对,经常改变,这个dll应该如何定义呢,程序又改如何调用呢
- Retcode : String; // 必须改 PChar;
- tmpchar:pchar;
- iPort : integer;
- sn,ID,No,PCode:Pchar;
- begin
- iCommPort := cmbComm1.ItemIndex +;
- setlength(Retcode,);// 尽量大
- tmpchar:=@Retcode[];
- tmpchar := ReadCardInfo_HF(iPort,SN,ID,No,PCode);
- setlength(Retcode,pos(#,Retcode));
PChar 实际是是一个指针,最好是加个返回长度,返回长度是不定的,只有dll里面才能确定,应该怎么加呢?
- 其实你按照 wql 的方法就可以做了的.
- var
- Retcode : String;
- iPort : integer;
- sn,ID,No,PCode,tmpchar:Pchar;
- begin
- iCommPort := cmbComm1.ItemIndex +;
- GetMem(TmpChar,);
- // 设定好 sn,id,no,pcode 的值
- TmpChar:= ReadCardInfo_HF(iPort,SN,ID,No,PCode);
- Retcode:=StrPas(TmpChar);
- freemem(TmpChar,);
- end;
- Delphi例子:
- function Test_GetXML(
- const XML : PChar;
- const XMLLen : Integer
- ):Integer;stdcall;
- var
- s : string;
- l : integer;
- begin
- s := '..........................';//获取值
- Result := Length(s); //值长度
- l := Result;
- if xmllen < l then l := xmllen; //处理分配长度不够的情况
- ZeroMemory(XML, XMLLen);
- CopyMemory(XML, @s[], l); //写入调用者分配的内存
- end;
- C#调用声明:
- public class Dll_Test
- {
- private const string Dll_FileName = @"D:\Test.dll";
- [DllImport(Dll_FileName)]
- public static extern int Test_GetXML(
- StringBuilder XML, //输出参数,XML文档内容,请分配足够的空间
- int XMLLen //上面分配空间大小
- ); //返回XML文档大小
- }
- C#调用:
- StringBuilder s = new StringBuilder();
- Dll_Test.Test_GetXML(
- s,
- s.Capacity
- );
- textbox.Text = s.ToString();
- 内存管理原则:谁分配的空间谁释放
- 你返回PChar的话,是DLL分配的内存,应该DLL释放,而调用者不知道DLL什么时候会释放,容易出错,特别在跨语言调用的情况下
- 所以参考WINAPI的约定写代码就行了
- //DLL
- function ReadInfo(iPort:Integer;SN,ID,No,PCode:Pchar):integer;stdcall;
- begin
- StrCopy (SN,PChar(''));
- StrCopy(ID,PChar(''));
- StrCopy(No,PChar(''));
- end;
- //调用
- var
- //使用静态分配内存的方式
- vSN,vID,vNo:array[..] of char;//视具体情况分配内存
- begin
- FillChar(vSN,,#);
- FillChar(vID,,#);
- FillChar(vNo,,#);
- ReadInfo(,vSN,vID,vNo);//vSN,vID,vNo就可以得到返回值了
- end;
- 或者 用动态分配内存的方式
- var
- vSN,vID,vNo:PChar;
- begin
- GetMem(vSN,);
- GetMem(vID,);
- GetMem(vNo,);
- ReadInfo(,vSN,vID,vNo);//vSN,vID,vNo就可以得到返回值了
- FreeMem(vSN);
- FreeMem(vID);
- FreeMem(vNo);
- end;
- function ReadInfo(iPort:Integer; SN,ID,No,PCode:Pchar):Pchar;stdcall;
- 或者可以使用
- function ReadInfo(iPort:Integer;SN,ID,No,PCode:WideString):WideString;stdcall;
- 由于返回值都是指针类型的数据。
- 只要传入的数据指针不为空,而且大小符合,就没有问题。
- 建议使用WideString,因为PChar在别的语言里调用有时候会有问题,而WideString是Windows的标准数据类型。
- 要分两种情况,主要是看谁分配内存。
- 第一种情况,DLL分配内存。这是针对 zhhg975 同学的。
- 函数定义不用改变,下面这样就可以,要改变的是它的实现
- function ReadInfo(iPort:Integer;var SN,ID,No,PCode:Pchar):Pchar;stdcall;
- begin
- //1 分别分配内存
- //2 将分配的内存分别赋给SN,ID,No,PCode
- //如 sn := pchar(AllocMem(Size));
- //返回值也一样 result := pchar(AllocMem(Size));
- //当然对SN[x]的赋值是必须的,否则总变化
- end;
- 第二种情况,调用程序分配内存,这时DLL中直接使用就可以了,不用再分配了。
- 注意,最好把关键字var去掉。当然返回值还是要分配内存的
- function ReadInfo(iPort:Integer;SN,ID,No,PCode:Pchar):Pchar;stdcall;
- begin
- //sn[x] := ....;
- //result := pchar(AllocMem(Size));
- //...
- end;
- 按照个人的用途可选用不同的内存分配函数。
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++没法接收一样。
例如:
- SendRcv2: function(cBegin: Pchar; SendMess: Pchar; ReturnMess: Pchar): PChar; stdcall;
- RMess := Sendrcv2('', Pchar(Value), pchar(sReturnStr));
- 。。。。。。
- constructor TShy.Create(Value, sfdm: string);
- var h: Integer;
- begin
- inherited create;
- h := LoadLibrary('SendRcv2.dll');
- if h <> then begin
- @SendRcv2 := GetProcAddress(h, 'SendRcv2');
- if @SendRcv2 = nil then begin
- // error
- end;
- end
- else begin
- // error
- end;
- 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下编辑
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm1 = class(TForm)
- Button1: TButton;
- procedure Button1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- {$R mydll.RES}
- //释放资源文件到指定文件夹,参数1:资源名称 参数2 资源类型,参数3:存放目录
- function ExtractRes(ResName,ResType, ResNewName: string): boolean;
- var
- Res: TResourceStream;
- begin
- try
- Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
- try
- Res.SavetoFile(ResNewName);
- Result := true;
- finally
- Res.Free;
- end;
- except
- Result := false;
- end;
- end;
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- ExtractRes('mydemoDll','RCDATA','d:/aaa.dll');
- end;
调用dll窗体
1.首先用delphi建一个dll工程:
- library Project2;
- uses
- SysUtils,
- Classes,
- Unit1 in 'Unit1.pas' {Form1}; //dll中的窗体为Form1
- procedure ShowTest();stdcall; //dll函数 用于显示窗体
- var
- f:TForm1;
- begin
- f:=TForm1.Create(nil);
- try
- f.ShowModal;
- finally
- f.Free;
- end;
- end;
- {$R *.res}
- exports
- ShowTest; //外部调用函数
- begin
- end.
2.新建Form1窗体,窗体为空窗体--》Unit1.pas。
- unit Unit1;
- interface
- uses
- Windows, SysUtils, Controls, Forms;
- type
- TForm1 = class(TForm)
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- end.
3. CTRL+F9编译dll。 编译成功,并生成Project2.dll
4.新建工程,Project1. 采用动态调用dll方式:
- unit Unit_main;
- interface
- uses
- Windows, SysUtils, Classes, Controls, Forms, StdCtrls;
- type
- TForm1 = class(TForm)
- Button1: TButton;
- procedure Button1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- procedure TForm1.Button1Click(Sender: TObject);
- type
- mypointer=Procedure();stdcall;
- var
- Handle:THandle;
- frm_p:mypointer;
- begin
- Handle:=loadlibrary('Project2.dll');
- if Handle> then
- begin
- frm_p:=GetProcAddress(Handle,'ShowTest');
- if @frm_p<>nil then frm_p;
- end;
- Freelibrary(Handle);
- end;
- end.
5. 修改Project1.dpr文件,加上Sharemem:
Sharemem已经说的很清楚了,如果的导出函数中参数或返回值有string类型,那么就需要引用ShareMem
至于你dll内部使用string类型跟引不引用ShareMem没关系,ShareMem只是解决dll中直接与外界
发生交互的string变量内存管理问题,比如何时释放啊该不该释放
- uses
- Sharemem ,Forms,
- Unit_main in 'Unit_main.pas' {Form1};
6. 运行Project1,点击Button1,实现调用出dll窗体。
Delphi中DLL的其他应用
1.DLL的入口函数和出口函数
- 在编写DLL时可以在DLL项目文件的begin..end之间加入DLL的进入口函数和出口函数,全局变量DLLProc是一个过程指针,指定入口/出口函数,初始值为nil,只需将自己的出入口函数赋值给它即可,自己的出入口函数必须传入一个DWord类型的参数。一下是出入口函数事件对应的用途。
- DLL_PROCESS_ATTACH 在进程启动或调用LoadLibrary( )时,DLL映射到当前进程的地址空间。在这个事件期间,D L L初始化实例数据
- DLL_PROCESS_DETACH DLL正从进程的地址空间分离出来,这也许是进程本身退出或调用了FreeLibrary( )。在该事件里,D L L也许没有初始化任何实例。
- DLL_THREAD_ATTACH 进程创建了一个新线程。这时,系统会调用所有和这个进程相关联的DLL入口函数。这个调用在新线程的环境中进行,用于分配线程特定的数据
- DLL_THREAD_DETACH 一个线程正在退出。在该事件里,DLL将释放线程特定的初始化数据
- 警告 调用TerminateThread()非正常终止线程时,没有调用DLL_THREAD_DETACH。
2.DLL中使用回调函数
回调函数一般被Win32DLL或其他DLL调用,而不是由应用程序调用。当调用回调函数时传递函数的地址。在DLL可以定义一种回调函数类型,然后将其做为导出函数的参数,实际应用程序调用DLL时需自己实现该回调函数类型,并传递实际类型参数。
案例一。
打开delphi新建一个dll,源码如下:
- library DLLEntry;
- uses
- SysUtils,
- Windows,
- Dialogs,
- Classes;
- {$R *.res}
- procedure DLLEntryPoint(dwReason:DWord); //入出口函数
- begin
- case dwReason of
- DLL_Process_Attach:showmessage('Attaching to process');
- DLL_PROCESS_DETACH:Showmessage('Detaching from process');
- DLL_THREAD_ATTACH:MessageBeep();
- DLL_THREAD_DETACH:MessageBeep();
- end;
- end;
- begin
- DllProc:=@DLLEntryPoint; //赋值给全局变量
- DLLEntryPoint(DLL_PROCESS_ATTACH); //传DWord类型值
- end.
调用dll,新建一个Delphi应用程序,在窗体上放置一个label和4个button控件。源码如下:
- unit mainFrm;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TTestThread=class(TThread) //定义线程
- procedure Execute;override;
- procedure SetCaptionData;
- end;
- TmainForm = class(TForm)
- btnLoadLib: TButton;
- btnFreeLib: TButton;
- btnCreateThread: TButton;
- btnFreeThread: TButton;
- lblCount: TLabel;
- procedure btnLoadLibClick(Sender: TObject);
- procedure btnFreeLibClick(Sender: TObject);
- procedure btnCreateThreadClick(Sender: TObject);
- procedure btnFreeThreadClick(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- private
- LibHandle:THandle;
- TestThread:TTestThread;
- Counter:Integer;
- GoThread:Boolean;
- public
- { Public declarations }
- end;
- var
- mainForm: TmainForm;
- implementation
- {$R *.dfm}
- procedure TTestThread.Execute(); //重写线程的Execute方法
- begin
- while mainForm.GoThread do
- begin
- Synchronize(SetCaptionData);
- Inc(mainForm.Counter);
- end;
- end;
- procedure TTestThread.SetCaptionData; //线程的异步方法修改label控件的caption
- begin
- mainForm.lblCount.Caption:=IntToStr(mainForm.Counter);
- end;
- procedure TmainForm.btnLoadLibClick(Sender: TObject); //载入dll
- begin
- if LibHandle= then
- begin
- LibHandle:=LoadLibrary('DLLEntry.dll');
- if LibHandle= then
- raise Exception.Create('Unable to Load DLL');
- end
- else
- MessageDlg('Library already loaded',mtWarning,[mbOK],);
- end;
- procedure TmainForm.btnFreeLibClick(Sender: TObject); //释放dll
- begin
- if not (LibHandle=) then
- begin
- FreeLibrary(LibHandle);
- LibHandle:=;
- end;
- end;
- procedure TmainForm.btnCreateThreadClick(Sender: TObject); //开启线程
- begin
- if TestThread=nil then
- begin
- GoThread:=True;
- TestThread:=TTestThread.Create(False);
- end;
- end;
- procedure TmainForm.btnFreeThreadClick(Sender: TObject); //释放线程
- begin
- if Assigned(TestThread) then
- begin
- GoThread:=False;
- TestThread.Free;
- TestThread:=nil;
- Counter:=;
- end;
- end;
- procedure TmainForm.FormCreate(Sender: TObject); //初始化操作
- begin
- LibHandle:=;
- TestThread:=nil;
- end;
- end.
新建一个dll,源码如下:
- library StrSrchLib;
- uses
- SysUtils,
- Windows;
- {$R *.res}
- type
- TFoundStrProc=procedure (StrPos:PChar);stdcall; //定义过程类型
- function SearchStr(ASrcStr,ASearchStr:PChar;AProc:TFarProc):Integer;stdcall; //字符串查找功能
- var
- FindStr:PChar;
- begin
- FindStr:=ASrcStr;
- FindStr:=StrPos(FindStr,ASearchStr); //查找ASearchStr在FindStr中出现位置
- while FindStr<>nil do
- begin
- if AProc<>nil then
- TFoundStrProc(AProc)(FindStr); //强制类型转换,将FindStr作为参数
- FindStr:=FindStr+;
- FindStr:=StrPos(FindStr,ASearchStr); //循环查找
- end;
- end;
- exports
- SearchStr;
- begin
- end.
新建Delphi应用程序,在窗体上放置一个edit 一个memo和一个button控件,源代码如下:
- unit CallTest;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TMainForm = class(TForm)
- btnCallDLLFunc: TButton;
- lblSrchWrd: TLabel;
- mmoStr: TMemo;
- edtSearchStr: TEdit;
- procedure btnCallDLLFuncClick(Sender: TObject);
- end;
- var
- MainForm: TMainForm;
- count:integer; //全局计数变量
- implementation
- {$R *.dfm}
- function SearchStr(ASrcStr,ASearchStr:PChar;AProc:TFarProc):Integer;stdcall;external 'StrSrchLib.dll'; //声明导入函数
- procedure StrPosProc(AStrPsn:PChar);stdcall; //具体的回调函数类型
- begin
- inc(count);
- end;
- procedure TMainForm.btnCallDLLFuncClick(Sender: TObject);
- var
- s,s2:string;
- begin
- count:=;
- SetLength(s,mmoStr.GetTextLen);
- mmoStr.GetTextBuf(PChar(s),mmoStr.GetTextLen); //这两句功能是将memo控件内容赋值给s字符串
- s2:=edtSearchStr.Text;
- SearchStr(PChar(s),PChar(s2),@StrPosProc);
- ShowMessageFmt('%s %s %d %s',[edtSearchStr.Text,'occurs',count,'times.']);
- end;
- 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
画圆就可以了:
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm1 = class(TForm)
- Button1: TButton;
- procedure Button1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1: TForm1;
- implementation
- uses GDIPAPI,GDIPOBJ;
- {$R *.dfm}
- procedure TForm1.Button1Click(Sender: TObject);
- var
- g: TGPGraphics;
- p: TGPPen;
- begin
- g := TGPGraphics.Create(Canvas.Handle);
- p := TGPPen.Create(aclRed, );
- {参数1颜色; 参数2是笔宽, 笔宽是可选, 默认 1}
- g.DrawEllipse(p, , , , );
- p.Free;
- g.Free;
- end;
- end.
dll函数
- type
- TDllFun = function (TestStr: PChar; Len: Integer): Integer;
- procedure TForm1.Button2Click(Sender: TObject);
- var
- GetStr: TDllFun;
- Dllhandle: HMODULE;
- TestStr: PChar;
- begin
- Dllhandle := LoadLibrary('Project2.dll');
- if Dllhandle <> then
- begin
- try
- GetStr := GetProcAddress(Dllhandle, 'GetStr');
- GetMem(TestStr, ); //字符串长度,自己设置
- GetStr(TestStr, );
- //使用
- ShowMessage(TestStr);
- FreeMem(TestStr);
- finally
- FreeLibrary(Dllhandle);
- end;
- end;
- end;
delphi dll调用问题的更多相关文章
- 在.net中调用Delphi dll的Pchar转换
Pchar是非托管代码,要在.net中调用Delphi dll中的功能,请使用MarshalAs属性告知.net调用PInvoke去转换.net中标准的string类型.如果Delphi dll是De ...
- Delphi动态调用C++写的DLL
c++ DLL 文件,建议用最简单的c++编辑工具.不会加入很多无关的DLL文件.本人用codeblocks+mingw.不像 VS2010,DLL编译成功,调用的时候会提示缺其他DLL. 系统生成的 ...
- Delphi 7调用C语言编写的DLL
DLL一定是要C语言导出的符号,也就是extern “C”. 当然,我们都知道DLL调用分为动态调用和静态调用. 动态调用的一般思想为,先LoadLibrary那个你想加载的DLL,然后通过GetPr ...
- Delphi Dll 动态调用例子(3)-仔细看一下
http://blog.163.com/bxf_0011/blog/static/35420330200952075114318/ Delphi 动态链接库的动态和静态调用 为了让人能快速的理解 静态 ...
- Delphi Dll 动态调用例子(2)
http://zhidao.baidu.com/question/157196792.html delphi动态调用DLL 写了个1.dll内容如下 library Project2; uses Sy ...
- C# 调用Delphi dll
delphi dll 源码: library dllres; type char10 = ..] of char; TMydata = packed record id: Integer; name: ...
- Delphi程序调用C#.Net编译的DLL并打开窗体(详解)
Delphi程序调用C#.Net编译的DLL并打开窗体(详解)最近用C#.Net写了一个公用模块, 本以为仅提供给.Net程序使用, 但是领导要求把这些功能提供给旧系统使用, 天啦, 几套旧系统全是D ...
- vb6如何调用delphi DLL中的函数并返回字符串?
1,问题描述 最近发现vb6调用delphi DLL中的函数并返回字符串时出现问题,有时正常,有时出现?号,有时干脆导致VB程序退出 -- :: 将金额数字转化为可读的语音文字:1转化为1元 ???? ...
- delphi 跨版本DLL调用嵌入窗体实现
delphi 能实现把别的DLL的窗体句柄查到后,贴到PANL之中,此类文章网上不少,而如果是delphi不同版本开发的DLL互调时,一些控件内部的定义有所区别,因为无法(至少目前我觉得理论上不可行) ...
随机推荐
- Oracle with as语法
with as优点 增加了sql的易读性,如果构造了多个子查询,结构会更清晰: 更重要的是:“一次分析,多次使用”,这也是为什么会提供性能的地方,达到了“少读”的目标 用法:给查询的语句起个别名 e. ...
- shell正则匹配IP地址
IP分成5大类: A类地址 ⑴ 第1字节为网络地址,其它3个字节为主机地址. ⑵ 范围:1.0.0.1—126.155.255.254 ⑶ 私有地址和保留地址: ① 10.X.X.X是私有地址(只能在 ...
- Android中的ImageView的getDrawableCache获取背景图片的时候注意的问题
获取ImageView的背景图片使用getDrawableCache方法,不要使用getDrawable方法,后者获取不到图片的. 1.在调用imageView.getDrawableCache()之 ...
- Linux v4l2编程(摄像头信息采集)
基于Linux3.4.2,自己做一点儿视频信息采集及网络传输的小实验,边做边学,一些基础知识同步整理..... 1. 定义 V4L2(Video For Linux Two) 是内核提供给应用程序访问 ...
- MySQL 时间戳与日期格式的相互转换(转)
1.UNIX时间戳转换为日期用函数: FROM_UNIXTIME() select FROM_UNIXTIME(1156219870); 输出:2006-08-22 12:11:10 2.日期转换为U ...
- 软件-平面设计-CorelDRAW:CorelDRAW
ylbtech-软件-平面设计-CorelDRAW:CorelDRAW CorelDRAW Graphics Suite是加拿大Corel公司的平面设计软件:该软件是Corel公司出品的矢量图形制作工 ...
- Mosaic
Mosaic 是最古老的WEB浏览器,这是个套件FOR WINDOWS(包括TCP/IP,拨号,EMAIL等).
- NTFS文件系统
一.Volume和Cluster 卷(Volume)和簇(Cluster)是NTFS用来描述物理磁盘的单位. 卷之间是相对独立的,卷的概念其实就是分区(Partition). 簇的引入是为了方便处理不 ...
- Gym 102082B : Arithmetic Progressions
戳这里看题目吧! 题目大意:给你一个长度为n(2<=n<=5000)的序列,没有重复的数字,序列中每个元素满足(0<=numi<=1e9).求一个最长的数列满足差分值相同(除n ...
- Struct和Union的sizeof计算
struct 结构体的大小不是简单的成员相加,要考虑存储空间的字节对齐 1.空结构体的大小为1 2.含有static的结构体在计算大小时不算上static变量,因为static存储在全局数据空间,而s ...