用*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
.
当有一个用 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
.