質問
FPC DLLからDelphiのString
の長さの長さの取得に問題があります。私はDLLからString
を取り戻すことができるので、これは奇妙なものですが、その長さを取得できません。
Delphi:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
function Test(const S: String): Integer; cdecl; external 'c:\Project1.dll';
var
A: String;
begin
A := 'test';
WriteLn(Test(A)); // 1 ?
ReadLn;
end.
.
FPC:
library project1;
{$mode ObjFPC}{$H+}
uses
Classes;
function Test(const A: String): Integer; cdecl; export;
begin
Result := Length(A);
end;
exports Test;
end.
. 解決
Delphi 2009+のString
は、以前のバージョンのUnicodeString
、およびAnsiString
です。
FPCのString
は常にAnsiString
で、UnicodeString
にマッピングされません。そしてAfaik、FPCの文字列型は、とにかくDelphiの文字列型とバイナリ互換ではありません。したがって、Delphi AnsiString
をFPC AnsiString
に、およびその逆に、およびUnicodeString
でも同じに渡すことはできません。
特に複数のコンパイラが関与している場合、特にFPCのString
モードを使用していないため、DLL境界よりもDelphi
値を渡してはいけません。あなたはよりポータブルになるようにあなたのDLLを再設計する必要があります:
FPC:
library project1;
{$mode ObjFPC}
{$H+}
uses
Classes;
function TestA(const A: PAnsiChar): Integer; cdecl; export;
begin
Result := Length(A);
end;
function TestW(const A: PWideChar): Integer; cdecl; export;
begin
Result := Length(A);
end;
exports TestA, TestW;
end.
.
Delphi:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
function Test(const S: PChar): Integer; cdecl; external 'Project1.dll' name {$IFDEF UNICODE}'TestW'{$ELSE}'TestA'{$ENDIF};
var
A: String;
begin
A := 'test';
WriteLn(Test(PChar(A)));
ReadLn;
end.
. 他のヒント
このモジュール境界にstring
を使用することはできません。Delphi Typeは単にFPCタイプとは異なります。それらが同じ名前を持つが、それはそれらを同じ型にしません。
実際には、両方のモジュールが同じコンパイラでコンパイルされていても、異なるタイプになり、異なるヒープを割り当て、相互コールには無効です。Delphiでは、Sharemem
とまったく同じコンパイラバージョンを使用できますが、それはかなり制約です。
UTF-16のPWideChar
やUTF-8のPAnsiChar
などの相互コップ式タイプを使用します。そのようにあなたのライブラリは制限されず、何でも相互に相互運用できます。