Chaînes entre FPC et Delphi
-
21-12-2019 - |
Question
J'ai du mal à obtenir la longueur String
en Delphi à partir d'une DLL FPC.Ce qui est bizarre parce que je peux obtenir le String
de retour de la DLL mais je n'arrive pas à obtenir sa longueur.
Delphes:
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.
La solution
String
dans Delphi 2009+ est UnicodeString
, et AnsiString
dans les versions antérieures.
String
dans FPC est toujours AnsiString
, il ne correspond jamais à UnicodeString
.Et AFAIK, les types de chaînes de FPC ne sont de toute façon pas compatibles binairement avec les types de chaînes de Delphi.Donc tu ne peux pas passer un Delphi AnsiString
à un FPC AnsiString
et vice versa, et de même pour UnicodeString
.
Tu ne devrais pas passer String
de toute façon, les valeurs dépassent les limites de la DLL, en particulier lorsque plusieurs compilateurs sont impliqués, et d'autant plus que vous n'utilisez pas les FPC. Delphi
mode.Vous devez repenser votre DLL pour qu'elle soit plus portable, par exemple :
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.
Delphes:
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.
Autres conseils
Vous ne pouvez pas utiliser string
à travers cette limite de module.Le type Delphi est simplement différent du type FPC.Il est vrai qu’ils portent le même nom mais cela ne fait pas d’eux le même type.
En fait, même si les deux modules étaient compilés avec le même compilateur, ils seraient de types différents, alloués sur des tas différents et non valides pour l'interopérabilité.En Delphi, vous pouvez utiliser Sharemem
et exactement la même version du compilateur mais c'est assez contraignant.
Utilisez un type convivial pour l'interopérabilité tel que PWideChar
pour UTF-16 ou PAnsiChar
pour UTF-8.De cette façon, votre bibliothèque n'est pas limitée et peut interagir avec n'importe quoi.