用*char调用dll,在Delphi中使用PAnsiChar或AnsiString?

Calling dll with *char, use PAnsiChar or AnsiString in Delphi?

当有一个用 C 语言编写的带有以下函数声明的 dll 时:

WORD StartDownloadTo(char * pFileName);

对于 Delphi 10.4,我应该将其转换为:

function StartDownloadTo(FileName: AnsiString): Word cdecl stdcall;

可以这样调用:

var
  filename: string;
begin
  StartDownloadTo(AnsiString(FileName));
end;

function StartDownloadTo(FileName: PAnsiChar): Word cdecl stdcall;

可以调用:

var
  filename: string;
begin
  StartDownloadTo(PAnsiChar(AnsiString(fileName)));
end;

两者似乎都有效。一个比另一个更好的原因我不知道吗?

你的声明都不正确。

正确的声明是:

function StartDownloadTo(FileName: PAnsiChar): Word; cdecl;

你在调用约定中搞错了。

虽然使用 AnsiString 可能看起来有效,但这实际上只是巧合。碰巧 AnsiString 变量指向字符串的第一个字符。为了在语义上正确,你应该使用 PAnsiChar.

此外,如果您的字符串为空,您需要传递一个指向 null-terminating 字符的指针,这就是将空字符串表示为 C 字符串的方式。但是,如果您将参数声明为 AnsiString,则空字符串会导致传递 nil。如果您使用 PAnsiChar,则调用代码中的 PAnsiChar 强制转换会导致对空字符串进行所需的处理。

但是请注意,您使用的 8 位文本将无法支持当前用户区域设置之外的任何字符。我希望看到 C 代码接受 const wchar_t *pFileName 而你的 Delphi 代码使用 PWideChar.