2

Delphi XE では、この関数を含むBASS オーディオ ライブラリを使用しています。

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 は問題ないように見えますが、渡すと BASS 関数が失敗します。私の最初のコード: PAnsiChar( url ) は BASS でうまく動作しますが、警告を出します。

では、警告なしで UnicodeString から PAnsiChar に取得する正しい方法は何ですか?

4

2 に答える 2

15

びっくりしました

BASS_StreamCreateURL(PAnsiChar( url ) [...]

動作します。urlがUnicode文字列の場合、各文字は2バイトを占有します。たとえば、文字列がtestである場合、次のようになります。

7400 6500 7300 7400 0000                t e s t #0                     (Unicode)

メモリ内。文字列がヌル文字(0000)で終わることに注意してください。

PAnsiChar(url)

このアドレスのメモリは。と見なす必要があることをコンパイラに通知しますAnsiString。ただし、上記のバイトシーケンスを考慮すると、この場合は「t」しか見つかりません。確かに、として、AnsiStringシーケンスは次のように解釈する必要があります

74 00 65 00 73 00 74 00 00 00           t #0 e #0 s #0 t #0 #0 #0      (Ansi)

これは文字列「t」で、ヌル文字(00)で終わります。

PAnsiChar(AnsiString(url))

一方、最初にユニコード文字列をansi文字列に変換します。つまり、次のようになります。

74 65 73 74 00                           t e s t #0                    (Ansi)

これは、ヌル文字()で終わる文字列「test」00です。

アップデート

私は(まだ)超能力者ではありませんが、おそらくバスライブラリはUnicodeStringこの関数への最初の引数としてaへのポインタを実際に必要としますか?それはなぜ一見奇妙に見えるのかを説明します

PAnsiChar(url)

動作します。ライブラリは「ねえ、ユニコード文字列へのポインタを教えてください。手動で処理します」と言うかもしれませんが、上記のコードはそれを実行します(ポインタは単なるポインタです(つまり、符号なし32ビット)。整数)...)。PAnsiCharしかし、もちろん、ライブラリはコンパイラに、が必要であり、通常PAnsiChar(SomeUnicodeString)は不良であると明示的に指示しているため、コンパイラは文句を言います。もちろん、これが当てはまる場合は、

PAnsiChar(AnsiChar(url))

動作しません。ライブラリはユニコード文字列の/アドレス/を期待しますが、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_StreamCreateURL

サンプルユニットからMain.pas

Channel := BASS_StreamCreateFile(FALSE, PChar(OpenDialog.FileName), 0, 0,
    0 {$IFDEF UNICODE} or BASS_UNICODE {$ENDIF});
于 2010-12-28T01:43:32.180 に答える
1

次のコードスニペットは、私の経験ではうまく機能します。 {$IFDEF UNICODE}またBASS_UNICODE {$ENDIF}

于 2011-10-10T14:02:55.717 に答える