Cadenas entre FPC y Delphi
-
21-12-2019 - |
Pregunta
Tengo problemas para conseguir la longitud String
en Delphi desde una DLL FPC.Lo cual es extraño porque puedo conseguir el String
desde la DLL pero no puedo obtener su longitud.
Delfos:
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.
Solución
String
en Delphi 2009+ es UnicodeString
, y AnsiString
en versiones anteriores.
String
en FPC es siempre AnsiString
, nunca se asigna a UnicodeString
.Y AFAIK, los tipos de cadenas de FPC no son compatibles binariamente con los tipos de cadenas de Delphi de todos modos.Entonces no puedes pasar un Delphi AnsiString
a un FPC AnsiString
y viceversa, y lo mismo para UnicodeString
.
no deberías estar pasando String
valores por encima del límite de DLL de todos modos, especialmente cuando hay varios compiladores involucrados, y especialmente porque no está utilizando FPC Delphi
modo.Necesita rediseñar su DLL para que sea más portátil, por ejemplo:
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.
Delfos:
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.
Otros consejos
No puede utilizar string
a través del límite de este módulo.El tipo Delphi es simplemente diferente del tipo FPC.Es cierto que tienen el mismo nombre pero eso no los convierte en el mismo tipo.
De hecho, incluso si ambos módulos se compilaran con el mismo compilador, serían de tipos diferentes, estarían asignados en diferentes montones y no serían válidos para la interoperabilidad.En Delphi podrías usar Sharemem
y exactamente la misma versión del compilador, pero eso es bastante restrictivo.
Utilice un tipo amigable para la interoperabilidad como PWideChar
para UTF-16 o PAnsiChar
para UTF-8.De esa manera su biblioteca no está limitada y puede interoperar con cualquier cosa.