I am having problems getting length of String
in Delphi from an FPC DLL. Which is weird because I can get the String
back from the DLL but I can't get its length.
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.
String
in Delphi 2009+ is UnicodeString
, and AnsiString
in earlier versions.
String
in FPC is always AnsiString
, it never maps to UnicodeString
. And AFAIK, FPC's string types are not binary compatible with Delphi's string types anyway. So you cannot pass a Delphi AnsiString
to a FPC AnsiString
and vice versa, and the same for UnicodeString
.
You should not be passing String
values over the DLL boundary anyway, especially when multiple compilers are involved, and especially since you are not using FPC's Delphi
mode. You need to redesign your DLL to be more portable, eg:
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.