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互调时,一些控件内部的定义有所区别,因为无法(至少目前我觉得理论上不可行) ...
随机推荐
- POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...
- Cent OS 7下安装 mongodb
1.下载MongoDB 安装包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.8.tgz 2.解压并安装 .tgz 3. ...
- WebGPU学习(九):学习“fractalCube”示例
大家好,本文学习Chrome->webgpu-samplers->fractalCube示例. 上一篇博文: WebGPU学习(八):学习"texturedCube"示 ...
- 线程组,action to be taken after a sampler error
continue:继续运行后面的请求 start next thread loop:后面的请求不执行,重新循环执行 stop thread:停止所有线程(等待正在执行的线程执行完后,失败的请求后面的 ...
- Xshell与securecrt对比
一.功能对比1.Xshell功能- 支持布局切换- 可调整Script执行顺序- 提供多标签功能- 对linux支持度高- 支持IPv6- 全球用户的多语言支持- 支持用户定义的键映射- 灵活和强大的 ...
- Linux下的解压缩
Linux下常见的压缩包格式有5种:zip tar.gz tar.bz2 tar.xz tar.Z 其中tar是种打包格式,gz和bz2等后缀才是指代压缩方式:gzip和bzip2 filename. ...
- 关于java使用json不能够使用报没有导包的问题,以及前后台交互json数据的使用
博客搬迁,给你带来的不便,敬请谅解! http://www.suanliutudousi.com/2017/12/02/%e5%85%b3%e4%ba%8ejava%e4%bd%bf%e7%94%a8 ...
- python-request模块--安装
Request是python中一个发送http请求的包, pip安装: pip install Requests (==版本号) 如果你没有安装pip那么需要先安装pip,pip是python中基本的 ...
- 23-python基础-python3-浅拷贝与深拷贝(1)
1.可变和不可变数据类型. 列表是‘可变的’数据类型,它的值可以添加.删除或改变. 字符串是‘不可变的’,它不能被更改. (1)字符串 尝试对字符串中的一个字符重新赋值,将导致TypeError错误. ...
- android中SharedPreferences
SharedPreferences:用于存储少量并且数据格式简单,基本上都是普通的字符串,标量类型的值,比如:应用程序的各种配置信息等. SharedPreferences:保存的数据格式主要是key ...