从Delphi DLL传递PChar

时间:2015-10-30 10:21:24

标签: delphi dll pchar

我如何从DLL传递pchar? DLL必须与其他应用程序兼容,而不仅仅是delphi。 在帮助中写道,将指针传递给局部变量是危险的,如果我们将此变量设为全局变量,则代码将不是线程安全的。

我们可以安全地传递一个宽字符串,但在这种情况下,该DLL将与其他(非Delphi)应用程序不兼容。

>>> my_list = [['mango','apple','mango'],['papaya','orange'],['berry','berry'],['watermelon','banana']]
>>> [lst if len(lst) == len(set(lst)) else [] for lst in my_list]
[[], ['papaya', 'orange'], [], ['watermelon', 'banana']]

1 个答案:

答案 0 :(得分:3)

您有三个主要选择。

让调用者分配被调用者填充的内存

function GetString(Buffer: PWideChar; BufferLen: Integer): Integer; stdcall;

调用者必须知道要分配多少内存。您可以通过安排函数返回复制的字符数来执行此操作,或者,如果Buffernil,则返回所需的缓冲区大小。所以调用者可能会像这样调用这个函数:

var
  str: string;
....
SetLength(str, GetString(nil, 0) - 1);
GetString(PChar(str), Length(str) + 1);

-1+1将处理空终止符。

让被叫方分配内存,并导出解除分配器

看起来像这样:

function GetString: PWideChar; stdcall;
function Free(P: Pointer); stdcall;

被调用者从内部堆中分配内存。但是被调用者还必须导出一个释放内存的函数。调用序列如下所示:

var
  P: PWideChar;    
  str: string;
....
P := GetString();
str := P;
Free(P);

对此的一种扭曲是分配共享堆,例如COM堆。这样您就不需要导出解除分配器,因为调用者可以在没有您帮助的情况下获取COM堆解除分配器。

返回COM字符串

COM BSTR是从共享COM堆分配的,任何Windows开发环境都可以使用这些对象。 Delphi将这些包装为WideString。但有一点是Delphi ABI与其他工具不同,您不能将WideString用作函数返回值并与其他工具互操作。相反,你应该使用out参数。

procedure GetString(out str: WideString); stdcall;

此处有更多详情:Why can a WideString not be used as a function return value for interop?