delphi:dll没有用于字符串传输的内存管理器
德尔福Xe 它被给出: 1.dll,其中包含一个单元delphi:dll没有用于字符串传输的内存管理器,delphi,dll,delphi-xe,Delphi,Dll,Delphi Xe,德尔福Xe 它被给出: 1.dll,其中包含一个单元 unit DllUnit; interface uses windows, sysutils; Procedure GuPrcA(var p:PAnsiChar;const l:integer); StdCall; Procedure GuPrcW(var p:PWideChar;const l:integer); StdCall; Exports GuPrcA,GuPrcW; implementation procedure Gu
unit DllUnit; interface
uses windows, sysutils;
Procedure GuPrcA(var p:PAnsiChar;const l:integer); StdCall;
Procedure GuPrcW(var p:PWideChar;const l:integer); StdCall;
Exports GuPrcA,GuPrcW;
implementation
procedure GuMes(s:string);
begin
MessageBox(0,pchar(s),'From dll',mb_iconinformation);
end;
Procedure GuPrcW(var p:PWideChar;const l:integer); // wide
var s:widestring;
begin
if (p=nil)or(l<1) then begin p:=nil;exit;end;
SetLength(s,trunc(l/sizeof(widechar)));Move(p^,Pointer(s)^,l);
gumes('l: '+inttostr(l)+', nl: '+inttostr(length(s))+#10+'-'+s+'-');
s:=widestring(Uppercase(s));Move(Pointer(s)^,p^,l);
end;
Procedure GuPrcA(var p:Pansichar;const l:integer); // ansi
var s:ansistring;
begin
if (p=nil)or(l<1) then begin p:=nil;exit;end;
SetLength(s,l);Move(p^,Pointer(s)^,l);
gumes('l: '+inttostr(l)+', nl: '+inttostr(length(s))+#10+'-'+s+'-');
s:=ansistring(AnsiUppercase(s));Move(Pointer(s)^,p^,l);
end;
Initialization
ReportMemoryLeaksOnShutdown:=true;
end.
要下载源代码,可以在以下位置下载:
通过按下按钮,在dll行(ansi或宽字符串)中传输,在msgbox dll中显示,在那里处理(空闲时间大写)并返回到程序。未使用内存管理器(fast-simple-sharem)。程序和dll中都包含ReportMemoryLeaksOnShutdown(显示有关内存丢失的事件),这两个都是静默的,也就是说,与所有程序一样,各处的行长度也过于一致
这是必要的:
SetLength(s, trunc(l/sizeof(widechar)));
Move(p^, Pointer(s)^, l);
您将最终导致程序堆损坏;我想你是说
SetLength(s, l);
Move(p^, Pointer(s)^, l * sizeof(widechar));
由于Dll在接口部分不使用托管字符串类型,因此它不需要共享内存管理器,并且可以与其他语言(如VB或C++/C#)一起使用。您太复杂了。Delphi语言/库将处理字符串和指向以null结尾的字符数组的指针之间的转换
unit DllUnit;
interface
uses
windows, sysutils;
Procedure GuPrcA(var p:PAnsiChar); StdCall;
Procedure GuPrcW(var p:PWideChar); StdCall;
Exports
GuPrcA,GuPrcW;
implementation
procedure GuMes(s:string);
begin
MessageBox(0,pchar(s),'From dll',mb_iconinformation);
end;
Procedure GuPrcW(var p:PWideChar); // wide
var
s: string;
begin
s := p;
gumes(s);
end;
Procedure GuPrcA(var p:Pansichar); // ansi
var
s: string;
begin
s := p;
gumes(s);
end;
Initialization
ReportMemoryLeaksOnShutdown:=true;
end.
调用例程也是如此
Procedure GuPrcA(var p:PansiChar); StdCall; external 'mydll.dll' name 'GuPrcA';
Procedure GuPrcW(var p:PwideChar); StdCall; external 'mydll.dll' name 'GuPrcW';
procedure TForm1.Button6Click(Sender: TObject);
var
s: UnicodeString;
begin
s := memo1.Text;
GuPrcW(PWideChar(s));
end;
procedure TForm1.Button7Click(Sender: TObject);
var
s: AnsiString;
begin
s := memo1.Text;
GuPrcA(PAnsiChar(s));
end;
我省略了您包含的所有诊断代码。如果要在显示文本之前或在将其传递到DLL之前对其进行修改,那么这很容易。在本地字符串变量中使用标准字符串操作进行修改(始终命名为s
)
例如:
Procedure GuPrcA(var p:Pansichar); // ansi
var
s: string;
begin
s := p;
s := s + '-' + Length(s);
gumes(s);
end;
或
底线是,您完全不需要编写在字符串和指针之间转换为以null结尾的字符数组的代码,因为Delphi将为您做这件事。如果您不想使用堆管理器传输数据,只需使用
WideString
类型的字符串即可
它会(稍微)慢一点,但它允许您更改每边的字符串长度
它将是真正的Unicode,所以在XE下使用本机DelphiUnicodeString
时,您不会遇到任何字符集之类的问题。您可以在代码中使用WideString
,到string
的转换将以静默方式完成
它将全部由Windows管理,因此即使是非Delphi库或应用程序(如.Net或C++)也可以直接处理它。setlength…=在dll和程序中?@serg奇怪的是,q中的代码传递的是字节大小而不是字符串length@david在任何情况下,OP代码对于奇数
l
值都是不正确的。您最好使用一行:SetString(s,p,l)
,它可以毫无问题地替换两个SetLength+Move。如果需要接收字符串,在dll中的输入处。如果有必要从Dll传输,请执行该移动。没什么大区别吗?没有。这里显示的一条线让我有点兴奋。问题:要在DLL中传输字符串,要在那里显示它(仅查看是否正确传输),\u要处理(转换/修改/ect)并返回到程序中。特别是宽字符串,在数组的中间可以是其他编码或2字节符号0,你是什么意思?没有什么?在所有情况下,我都认为使用字符串作为缓冲区比手动内存分配更容易。如果是,为什么?字符串列表?通常使用双空终止完成。+1是的,WideString
,也称为BSTR
,是互操作的一个很好的选择。您是如何使用这种编码风格的-/@不,你不能。你有一个很大的问题,就是你没有缩进你的代码。更大的问题是没有换行符和无用的前缀符号。
Procedure GuPrcA(var p:Pansichar); // ansi
var
s: string;
begin
s := p;
s := s + '-' + Length(s);
gumes(s);
end;
procedure TForm1.Button7Click(Sender: TObject);
var
s: AnsiString;
begin
s := memo1.Text;
s := s + '-' + Length(s);
GuPrcA(PAnsiChar(s));
end;