In Delphi XE I am using the BASS audio library, which contains this function:
function BASS_StreamCreateURL(url: PAnsiChar; offset: DWORD; flags: DWORD;
proc: DOWNLOADPROC; user: Pointer):HSTREAM; stdcall; external bassdll;
The 'url' parameter is of type PAnsiChar, so in my code I do a cast:
FStreamHandle := BASS_StreamCreateURL(PAnsiChar( url ) [...]
The compiler emits a warning on this line: "suspicious typecast of string to PAnsiChar". In trying to eliminate the warning, I found that the recommended way is to use a double cast:
FStreamHandle := BASS_StreamCreateURL(PAnsiChar( AnsiString( url )) [...]
This does eliminate the warning, but the BASS function now returns error code 2 ("cannot open file"), which tells me the URL string it receives is somehow broken. I cannot see what the bass DLL actually receives, but using a breakpoint in the debugger the string looks good:
var
s : PAnsiChar;
begin
s := PAnsiChar( AnsiString( url ));
At this point string s appears fine, but the BASS function fails when I pass it. My initial code: PAnsiChar( url ) works well with BASS, but emits a warning.
So what's the correct way of getting from UnicodeString to PAnsiChar without a warning?
I am amazed that
works. If
url
is a unicode string, each character will occupy two bytes. If, for instance, the string istest
, it will readin memory. Notice that the string ends at the null character (
0000
) When you doyou will tell the compiler that the memory at this address should be thought of as an
AnsiString
. But if you consider the above sequence of bytes, you will find only "t" in this case. Indeed, as anAnsiString
, the sequence should be interpreted aswhich is the string "t", ending with the null character (
00
).on the other hand will first convert the unicode string to an ansi string, that is, you will obtain
which is the string "test" ending with the null character (
00
).Update
I am not psychic (yet), but maybe the Bass library actually does require a pointer to a
UnicodeString
as the first argument to this function? That would explain why the seemingly oddworks. The library might say "Hey, just give me the pointer to the unicode string, and I'll do some manual processing with it" and the code above does just that (a pointer is just a pointer (that is, an unsigned 32 bit integer)...). But the compiler will complain, of course, because the library explicity told the compiler that it will require a
PAnsiChar
, and normallyPAnsiChar(SomeUnicodeString)
is bad. If this is the case, of course, then,doesn't work. The library expects /the address of/ a unicode string, but gets /the address of/ an ansi string.
Update 2
If my hypothesis in Update 1 is correct, the declaration
would make the skies blue again.
Update 3
From the documentation:
I bet that the problem will go away if you specify this flag when you call
BASS_StreamCreateURL
!From the sample unit
Main.pas
: