FreeString呼び出しを使用せずにDLLとDelphiアプリケーション間で文字列を交換する1つの方法は、呼び出し元のアプリケーションから文字列バッファをPCharとして取得し、DLLのバッファを埋めることです。これが、呼び出し元のアプリケーションと文字列を交換する必要がある場合のWindowsAPI関数の動作です。
これを行うために、呼び出し元のアプリケーションは文字列バッファーを作成し、そのバッファーを参照するPCharをバッファーサイズとともにDLL関数に送信します。バッファサイズがDLLがアプリケーションに送信する必要のある実際の文字列よりも小さい場合、DLL関数は、バッファに必要な実際のサイズを呼び出し元のアプリケーションに送信できます。
デフォルトではDelphi2010とWideStringでどのように動作しますか:FreePascalでもWidePCharを強制する必要がありますか?
Delphi2009およびDelphi2010では、PCharはPWideCharと同じです。以前のバージョンのDelphiでは、そして私が知る限り、FreePascalではPCharはPAnsiCharと同じです。したがって、DLLからPCharを返す場合、コードはDelphi2010で正しく機能しません。明示的にPAnsiCharまたはPWideCharを使用する必要があります。再びWindowsAPI関数をたどることができます。これらは、多くのAPI関数の2つのバージョンを提供します。1つは名前にサフィックスとしてW文字が付いたWideCharをサポートし、もう1つは名前にサフィックスとしてA文字が付いたANSIサポートを備えています。
DLL関数の宣言は次のようになります。
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean;
function AStringFuncA(Buffer: PAnsiChar; var BufferSize: Integer): Boolean;
編集:
サンプルコードは次のとおりです。
1-widecharのDLL関数は次のようになります。
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
var
MyOutputStr : WideString;
begin
Result := False;
// Calculate your output string here.
MyOutputStr := 'This is a sample output';
// Check if buffer is assigned, and its given length is enough
if Assigned(Buffer) and (BufferSize >= Length(MyOutputStr) + 1) then
begin
//Copy output string into buffer
StrPCopy(Buffer,MyOutputStr);
Result := True;
end;
//Return actual size of output string.
BufferSize := Length(MyOutputStr) + 1;
end;
AnsiCharバージョンの場合、AnsiStringとPAnsiCharで同じコードを使用するか、ANSI文字列パラメーターをUnicodeに変換し、AStringFuncA関数内でAStringFuncWを呼び出してから、戻り文字列をAStringFuncWからPAnsiCharに変換できます。
2-DLLクライアントが使用するインターフェイスユニットでこれらの関数を定義する方法は次のとおりです。
unit TestDLLIntf;
interface
const
TestDll = 'Test.dll';
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
function AStringFuncA(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
function AStringFunc(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
implementation
function AStringFuncW; external TestDll name 'AStringFuncW';
function AStringFuncA; external TestDll name 'AStringFuncA';
{$IFDEF UNICODE}
function AStringFunc; external TestDll name 'AStringFuncW';
{$ELSE}
function AStringFunc; external TestDll name 'AStringFuncA';
{$ENDIF}
end.
上記のコードでは、AStringFuncW関数とAStringFuncA関数の両方が外部関数として宣言されています。AStringFunc関数は、Delphi 2009〜2010のWideCharバージョンを参照し、他のバージョンのAnsiCharバージョンを参照します。
3-ここでは、DLLクライアントが関数をどのように使用できるかを確認できます。
procedure TForm1.Button1Click(Sender: TObject);
var
Str : string;
Size : Integer;
begin
// Retrieve required buffer size
AStringFunc(nil,Size);
// Set buffer
SetLength(Str,Size);
// Retrieve output string from DLL function.
if AStringFunc(PChar(Str),Size) then
ShowMessage(Str);
end;
上記のコードでは、クライアントアプリケーションは最初にAStringFuncから実際の出力サイズを取得し、次に文字列バッファを設定し、DLLから出力文字列を取得します。AStringFuncは、コンパイラがUnicodeをサポートしているかどうかに応じて、DLL内のAStringFuncAまたはAStringFuncWのいずれかを参照するため、DelphiのUnicodeバージョンと非Unicodeバージョンの両方で同じコードが機能することに注意してください。