delphi dll调用问题

本文探讨了在Delphi中创建和使用DLL时遇到的问题,特别是关于字符串传递的实现方法。建议避免使用string作为DLL参数或返回值,推荐使用Pchar以提高兼容性。还提到了DLL内存管理,尤其是当DLL和调用程序使用不同的内存管理器时,需要引用ShareMem单元以统一管理。此外,文章强调了DLL设计应遵循标准WIN32 API参数类型,以增强复用性和跨语言兼容性。
摘要由CSDN通过智能技术生成

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:=1 to L do
begin
str1:=str1+Chr(i mod 256 ); i:=i div 256 ;
end ;
result:=Pchar(str1);//在应用程序中调用时返回值出错
end;
View Code

原函数是

Function IntToBin(N:Int64;L:Byte):String;
var
i: Int64 ;
j: Byte ;
str1:string;
begin
Result:='';str1:='';
i:= N ;
for j:=1 to L do
begin
str1:=str1+Chr(i mod 256 ); i:=i div 256 ;
end ;
result:=str1;
end;
View Code

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.
View Code

Dll中传送Pchar类型

procedure GetMsg(ret:Integer;Msg:PChar);stdcall;
begin  
StrPCopy(Msg,'OK');  
end;    
var 
 P:Pchar;  
begin  
P:=stralloc(1024);  
GetMsg(100,P);  
showmessage(P);  
strdispose(P);  
end;
View Code

dll传进传出字符串

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

function p_string(var s:pchar):pchar;stdcall;
begin 
s := '123';
Result := s;

end;

exports p_string;
View Code

做好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';
implementati
Delphi中制作DLL •一 Dll的制作一般分为以下几步: 1 在一个DLL工程里一个过程或函数 2 一个Exports关键字,在其下过程的名称。不用参数和调用后缀。 二参数传递 1 参数类型最好与window C++的参数类型一致。不要用DELPHI的数据类型。 2 最好有返回值[即使是一个过程],来报出调用成功或失败,或状态。成功或失败的返回值最好为1[成功]或0[失败].一句话,与windows c++兼容。 3 用stdcall声明后缀。 4 最好大小敏感。 5 无须用far调用后缀,那只是为了与windows 16位程序兼容。 三 DLL的初始化和退出清理[如果需要初始化和退出清理] 1 DLLProc[SysUtils单元的一个Pointer]是DLL的入口。在此你可用你的函数替换了它的入口。但你的函数必须符合以下要求[其实就是一个回调函数]。如下: procedure DllEnterPoint(dwReason: DWORD);far;stdcall; dwReason参数有四种类型: DLL_PROCESS_ATTACH:进程进入时 DLL_PROCESS_DETACH进程退出时 DLL_THREAD_ATTACH 线程进入时 DLL_THREAD_DETACH 线程退出时 在初始化部分: DLLProc := @DLLEnterPoint; DllEnterPoint(DLL_PROCESS_ATTACH); 2 如Form上有TdcomConnection组件,就Uses Activex,在初始化时一句CoInitialize (nil); 3 在退出时一定保证DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。 四全局变量的使用 在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份, 但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据 传递,除非你用内存映像文件。 五、其他:调用方式按照标准的Windows调用方式. 六、关于参数传递 •Delphi程序之间调用DLL,如果要用String类型的话,要在引用的单元加上ShareMem 单元。 •如果DelphiDLL供其他开发工具使用的话,不要使用String类型,用PAnsiChar类型。 尽量使用标准DLL接口。指的是传递的参数类型及函数返回类型不能是Delphi特有的, 比如string(AnsiString),以及动态数组和含有这些类型成员的复合类型(如记录),也不 能是包含有这些类型成员数据成员的对象类型,以避免可能的错误。如果使用了string类型或 动态数组类型,且调用方不是Delphi程序,则基本上会报错。如果调用方是Delphi调用方或 被调用方没有在工程文件的第一包含单元不是ShareMem,也可能会出错。 七、关于回调Funciton 你可以把Callback函数看作是一种特殊的消息响应函数,一般来说我们不会自己调用这种函数, 而是有某些系统函数调用,而且不需要向后传递消息。 只要象C/C++这样支持函数指针的语言都 有回调函数的概念,它实际上是向被调用函数传一个你的函数地址,然后被调用函数向通过你传 入的函数地址来调用你的函数 。 以上是结构化回调,到高级语言Object Pascal、C++中回调函数并没有退出,反而得到延伸与 扩展,在面向对像中的回调,其实是指面向对像中类对像的事件,事件就是原始的回调函数。面 向对像, 将回调函数定义成事件过程,在程序引用对像时,若指定了对像的过程事件后,那么在 要进行事件触发的地方检查事件过程是否分配,如果分中的就执行事,也就是执行了回调函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值