Stringhe tra FPC e Delphi
-
21-12-2019 - |
Domanda
Sto avendo problemi a ottenere la lunghezza di String
in Delphi da una DLL FPC.Il che è strano perché posso ottenere il String
torna dalla DLL ma non riesco a ottenere la sua lunghezza.
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.
PCF:
library project1;
{$mode ObjFPC}{$H+}
uses
Classes;
function Test(const A: String): Integer; cdecl; export;
begin
Result := Length(A);
end;
exports Test;
end.
Soluzione
String
in Delphi 2009 + è UnicodeString
, e AnsiString
nelle versioni precedenti.
String
in FPC è sempre AnsiString
, non mappa mai a UnicodeString
.E AFAIK, i tipi di stringhe di FPC non sono comunque compatibili con i tipi di stringhe di Delphi.Quindi non puoi passare un Delphi AnsiString
ad un FPC AnsiString
e viceversa, e lo stesso per UnicodeString
.
Non dovresti passare String
valori sopra il limite DLL comunque, specialmente quando sono coinvolti più compilatori e soprattutto perché non si utilizzano FPC Delphi
modalità.È necessario riprogettare la DLL per essere più portatile, ad es:
PCF:
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.
Altri suggerimenti
Non puoi usare string
attraverso questo limite del modulo.Il tipo Delphi è semplicemente diverso dal tipo FPC.È vero che hanno lo stesso nome ma questo non li rende dello stesso tipo.
Infatti, anche se entrambi i moduli fossero compilati con lo stesso compilatore, sarebbero tipi diversi, allocati da heap diversi e non validi per l'interoperabilità.A Delphi puoi usare Sharemem
e la stessa identica versione del compilatore, ma che è piuttosto vincolante.
Utilizzare un tipo di interoperabilità amichevole come PWideChar
per UTF-16 o PAnsiChar
per UTF-8.In questo modo la tua libreria non è vincolata e può interagire con qualsiasi cosa.