delphi - 处理这个字符串问题的优雅方法。 (Unicode-PAnsiString 问题)

标签 delphi unicode

考虑以下场景:

type 
PStructureForSomeCDLL = ^TStructureForSomeCDLL;
TStructureForSomeCDLL = record 
  pName: PAnsiChar;
end

function FillStructureForDLL: PStructureForSomeDLL;
begin
  New(Result);
  // Result.pName := PAnsiChar(SomeObject.SomeString);  // Old D7 code working all right
  Result.pName := Utf8ToAnsi(UTF8Encode(SomeObject.SomeString));  // New problematic unicode version
end;

...code to pass FillStructureForDLL to DLL...

unicode 版本中的问题是,所涉及的字符串转换现在会在堆栈上返回一个新字符串,并在 FillStructureForDLL 调用结束时回收该字符串,从而使 DLL 留下损坏的数据。在旧的 D7 代码中,没有中间转换函数,因此没有问题。

我当前的解决方案是像下面这样的转换器函数,在我看来这太黑客了。有没有更优雅的方法来达到相同的结果?

var gKeepStrings: array of AnsiString;

{ Convert the given Unicode value S to ANSI and increase the ref. count 
  of it so that returned pointer stays valid }
function ConvertToPAnsiChar(const S: string): PAnsiChar;
var temp: AnsiString;
begin
  SetLength(gKeepStrings, Length(gKeepStrings) + 1);
  temp := Utf8ToAnsi(UTF8Encode(S));
  gKeepStrings[High(gKeepStrings)] := temp; // keeps the resulting pointer valid 
                                            // by incresing the ref. count of temp.
  Result := PAnsiChar(temp);
end;

最佳答案

一种方法可能是在问题成为问题之前解决它,我的意思是调整 SomeObject 类,以便为您维护 SomeString 的 ANSI 编码版本(ANSISomeString?)以及原始版本SomeString,将两者保持在 SomeString 属性的“setter”中(使用您已经执行的相同 UTF8 > ANSI 转换)。

在非 Unicode 版本的编译器中,使 ANSISomeString 只是 SomeString 字符串的“副本”,这当然不是副本,而只是 SomeString 上的附加引用计数。在 Unicode 版本中,它引用与原始 SomeString 具有相同“生命周期”的单独 ANSI 编码。

procedure TSomeObjectClass.SetSomeString(const aValue: String);
begin
  fSomeString := aValue;

{$ifdef UNICODE}
  fANSISomeString := Utf8ToAnsi(UTF8Encode(aValue));
{$else}
  fANSISomeString := fSomeString;
{$endif}
end;

在您的 FillStructure... 函数中,只需更改代码以引用 ANSISomeString 属性 - 这完全独立于是否针对 Unicode 进行编译。

function FillStructureForDLL: PStructureForSomeDLL;
begin
  New(Result);
  result.pName := PANSIChar(SomeObject.ANSISomeString);
end;

关于delphi - 处理这个字符串问题的优雅方法。 (Unicode-PAnsiString 问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1452215/

相关文章:

json - Delphi:JSON 数组

delphi - 如何禁用/隐藏表单中的图标?

java - 为什么这个表情符号正则表达式也匹配数字

delphi - 修改 Windows 7 预览 Pane 以显示文件夹的子目录而不是大的空框

delphi - 计算两个日期之间的天数

delphi - 如何将RETRIEVAL_POINTERS_BUFFER结构翻译为Delphi?

python - 使用 Python3 读取 srt(字幕)文件

javascript - 给伪元素添加图标

java - 在java框架中设置unicode字符

Jquery插入unicode而不是符号