2014-02-25 28 views
1

我在Delphi中从FPC DLL获取String的长度时遇到问题。这很奇怪,因为我可以从DLL中取回String,但我无法获得它的长度。FPC和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. 

回答

3

String在Delphi 2009+中是UnicodeStringAnsiString在早期版本中。

String在FPC总是AnsiString,它从不映射到UnicodeString。而AFAIK,FPC的字符串类型与Delphi的字符串类型不是二进制兼容的。因此,您无法将德尔福AnsiString传递给FPC AnsiString,反之亦然,并且UnicodeString也是如此。

你不应该在DLL边界反正路过String值,尤其是当多个编译器都参与其中,特别是因为你没有使用FPC的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. 

德尔福:

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. 
+0

没有执行转换,也没有性能损失。如果UnicodeString为空,则将'UnicodeString'强制转换为'PWideChar'只会检索指向UnicodeString字符数据的指针或指向静态'#0'字符的指针。 –

+0

PWideChar创造奇迹! – user3060326

+0

FPC中的字符串总是AnsiString,Delphi中的AnsiString或UnicodeString似乎并不重要。最好强调FPC.AnsiString不等于Delphi.AnsiString。 –

1

不能跨越这个模块边界使用string。 Delphi类型与FPC类型简单不同。确实,他们有相同的名字,但不会使他们成为同一类型。

事实上,即使两个模块都使用相同的编译器进行编译,它们也会是不同的类型,分配给不同的堆并且不适用于互操作。在德尔福你可以使用Sharemem和完全相同的编译器版本,但这是非常有限的。

使用互操作性友好类型,如UTF-16的PWideChar或UTF-8的PAnsiChar。这样,你的图书馆不受限制,可以与任何事物互操作。

+0

@Ritsaert这就是我说的,我认为。 –

+0

@Ritsaert我从来没有说现在的类型是一样的。其实我说他们是不同的句号。您只能通过强制使用相同的编译器和共享内存管理器来使它们相同。我看不出有什么问题。 –

+0

@DavidHeffernan解决方案是'{$ mode delphiunicode}'。我可以有本地的String interop。 – user3060326

相关问题