Delphi-XE中UnicodeString到PAnsiChar的转换
在Delphi XE中,我使用的是,它包含以下函数:Delphi-XE中UnicodeString到PAnsiChar的转换,delphi,pointers,delphi-xe,unicode-string,ansistring,Delphi,Pointers,Delphi Xe,Unicode String,Ansistring,在Delphi XE中,我使用的是,它包含以下函数: function BASS_StreamCreateURL(url: PAnsiChar; offset: DWORD; flags: DWORD; proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll; “url”参数的类型为PAnsiChar,因此在我的代码中,我执行了一个强制转换: FStreamHandle := BASS_StreamC
function BASS_StreamCreateURL(url: PAnsiChar; offset: DWORD; flags: DWORD;
proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
“url”参数的类型为PAnsiChar,因此在我的代码中,我执行了一个强制转换:
FStreamHandle := BASS_StreamCreateURL(PAnsiChar( url ) [...]
编译器在这一行发出警告:“可疑的字符串类型转换为PAnsiChar”。在试图消除警告时,我建议使用双重强制转换:
FStreamHandle := BASS_StreamCreateURL(PAnsiChar( AnsiString( url )) [...]
这确实消除了警告,但是BASS函数现在返回错误代码2(“无法打开文件”),它告诉我它接收到的URL字符串不知何故被破坏了。我看不到bass DLL实际接收到什么,但在调试器中使用断点,字符串看起来不错:
var
s : PAnsiChar;
begin
s := PAnsiChar( AnsiString( url ));
此时字符串s看起来很好,但当我传递它时,低音功能失败。我的初始代码:PAnsiChar(url)与BASS配合得很好,但会发出警告
那么,在没有任何警告的情况下,从独角兽毁灭到潘斯卡尔的正确方式是什么呢?我很惊讶
BASS_StreamCreateURL(PAnsiChar( url ) [...]
工作。如果url
是unicode字符串,则每个字符将占用两个字节。例如,如果字符串是test
,它将读取
7400 6500 7300 7400 0000 t e s t #0 (Unicode)
在记忆中。请注意,执行此操作时,字符串以空字符(0000
)结尾
PAnsiChar(url)
您将告诉编译器,此地址的内存应被视为一个AnsiString
。但是如果你考虑上面的字节序列,在这种情况下你只会发现“t”。事实上,作为一个应答
,序列应该被解释为
74 00 65 00 73 00 74 00 00 00 t #0 e #0 s #0 t #0 #0 #0 (Ansi)
这是字符串“t”,以空字符(00
)结尾
另一方面,将首先将unicode字符串转换为ansi字符串,也就是说,您将获得
74 65 73 74 00 t e s t #0 (Ansi)
这是以空字符(00
)结尾的字符串“test”
更新
我还不是通灵者,但也许Bass库确实需要一个指向UnicodeString的指针作为该函数的第一个参数?这就解释了为什么这看起来很奇怪
PAnsiChar(url)
工作。库可能会说“嘿,给我一个指向unicode字符串的指针,我会用它进行一些手动处理”,上面的代码就是这么做的(指针就是一个指针(即,一个无符号的32位整数)…)。但是编译器当然会抱怨,因为库明确地告诉编译器它需要一个PAnsiChar
,通常PAnsiChar(destring)
是坏的。当然,如果是这样的话
PAnsiChar(AnsiChar(url))
不起作用。库需要/unicode字符串的地址,但获取/ansi字符串的地址
更新2
如果我在更新1中的假设正确,声明
function BASS_StreamCreateURL(url: PWideChar; offset: DWORD; flags: DWORD;
proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
会让天空再次蔚蓝
更新3
从文件中:
注意:Delphi 2009用户应尽可能使用BASS_UNICODE标志
我敢打赌,如果在调用BASS\u StreamCreateURL
时指定此标志,问题就会消失
从样本单元Main.pas
:
Channel := BASS_StreamCreateFile(FALSE, PChar(OpenDialog.FileName), 0, 0,
0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
根据我的经验,以下代码片段非常有用。
{$IFDEF UNICODE}
或BASS_UNICODE{$ENDIF}
我完全同意你的分析。然而,“Susticiuos”类型转换是有效的,而应该正确的类型转换会产生BASS的错误。Delphi XE和2009中的行为相同。(BASS附带的一个演示也使用了从string到PAnsiChar的简单转换。)更新3:BASS_UNICODE标志确实出现在我的代码中。你之前的预感可能是对的。由于指定了标志,因此BASS需要PWideChar,即使声明中另有说明。非常感谢,安德烈亚斯!我刚刚使用了AnsiString AnsiString:myURL;myURL:='http://...'BASS_StreamCreateURL(PAnsiChar(myURL),0,[…],并在Delphi XE2上工作
Channel := BASS_StreamCreateFile(FALSE, PChar(OpenDialog.FileName), 0, 0,
0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});