问题描述
使用以下函数声明用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
。
此外,如果您的字符串为空,则需要将指针传递给以零结尾的字符,这就是将空字符串表示为C字符串的方式。但是,如果将参数声明为AnsiString
,则空字符串将导致传递nil
。如果您使用PAnsiChar
,则调用代码中的PAnsiChar
强制转换会导致对空字符串进行所需的处理。
但是请注意,使用8位文本将无法支持当前用户语言环境之外的任何字符。我希望看到C代码接受const wchar_t *pFileName
,并且您的Delphi代码使用PWideChar
。