Mar*_*ski 2 delphi pointers unicode-string ansistring delphi-xe
在Delphi XE中,我使用的是BASS音频库,它包含以下功能:
function BASS_StreamCreateURL(url: PAnsiChar; offset: DWORD; flags: DWORD;
proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
Run Code Online (Sandbox Code Playgroud)
'url'参数的类型为PAnsiChar,所以在我的代码中我做了一个强制转换:
FStreamHandle := BASS_StreamCreateURL(PAnsiChar( url ) [...]
Run Code Online (Sandbox Code Playgroud)
编译器在此行上发出警告:"对PAnsiChar的字符串的可疑类型转换".在试图消除警告时,我发现推荐的方法是使用双重投射:
FStreamHandle := BASS_StreamCreateURL(PAnsiChar( AnsiString( url )) [...]
Run Code Online (Sandbox Code Playgroud)
这确实消除了警告,但是BASS函数现在返回错误代码2("无法打开文件"),这告诉我它收到的URL字符串以某种方式被破坏.我无法看到低音DLL实际接收到的内容,但在调试器中使用断点时字符串看起来很好:
var
s : PAnsiChar;
begin
s := PAnsiChar( AnsiString( url ));
Run Code Online (Sandbox Code Playgroud)
此时字符串s显示正常,但是当我通过它时BASS功能失败.我的初始代码:PAnsiChar(url)与BASS配合良好,但会发出警告.
那么在没有警告的情况下从UnicodeString到PAnsiChar的正确方法是什么?
And*_*and 15
我很惊讶
BASS_StreamCreateURL(PAnsiChar( url ) [...]
Run Code Online (Sandbox Code Playgroud)
作品.如果url
是unicode字符串,则每个字符将占用两个字节.例如,如果字符串是test
,则它将读取
7400 6500 7300 7400 0000 t e s t #0 (Unicode)
Run Code Online (Sandbox Code Playgroud)
在记忆中.请注意,字符串以空字符结束(0000
)
PAnsiChar(url)
Run Code Online (Sandbox Code Playgroud)
你会告诉编译器这个地址的内存应该被认为是一个AnsiString
.但是如果考虑上面的字节序列,在这种情况下你只会发现"t".实际上,作为一个AnsiString
,序列应该被解释为
74 00 65 00 73 00 74 00 00 00 t #0 e #0 s #0 t #0 #0 #0 (Ansi)
Run Code Online (Sandbox Code Playgroud)
这是字符串"t",以空字符(00
)结尾.
PAnsiChar(AnsiString(url))
Run Code Online (Sandbox Code Playgroud)
另一方面,首先会将unicode字符串转换为ansi字符串,也就是说,您将获得
74 65 73 74 00 t e s t #0 (Ansi)
Run Code Online (Sandbox Code Playgroud)
这是以空字符(00
)结尾的字符串"test" .
我不是通灵的,但也许Bass库实际上确实需要指向a的指针UnicodeString
作为这个函数的第一个参数?这可以解释为什么看似奇怪
PAnsiChar(url)
Run Code Online (Sandbox Code Playgroud)
作品.库可能会说"嘿,只要给我指向unicode字符串的指针,我就用它做一些手动处理",上面的代码就是这样(指针只是一个指针(也就是说,一个无符号的32位)整数)...).但编译器会抱怨,当然,因为库明确告诉编译器它需要一个PAnsiChar
,而且通常PAnsiChar(SomeUnicodeString)
是坏的.如果是这种情况,那么,当然,
PAnsiChar(AnsiChar(url))
Run Code Online (Sandbox Code Playgroud)
不起作用.库需要/一个unicode字符串的地址,但是得到/一个ansi字符串的地址.
如果我在Update 1中的假设是正确的,那么声明
function BASS_StreamCreateURL(url: PWideChar; offset: DWORD; flags: DWORD;
proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
Run Code Online (Sandbox Code Playgroud)
会让天空变成蓝色.
从文档:
注意:Delphi 2009用户应尽可能使用BASS_UNICODE标志
我敢打赌,如果你在打电话时指定这个标志,问题就会消失BASS_StreamCreateURL
!
来自样本单位Main.pas
:
Channel := BASS_StreamCreateFile(FALSE, PChar(OpenDialog.FileName), 0, 0,
0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
Run Code Online (Sandbox Code Playgroud)