将FPC的.o文件链接到Delphi中

4

我该如何将库中的FPC .o文件链接到Delphi可执行文件中。当我尝试链接以下代码时,会出现许多未满足的前向或外部声明。

library project1;

{$mode objfpc}{$H+}

uses
  Classes
  { you can add units after this };

function Test: Integer;
begin
  Result := -1;
end;

begin
end.


[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'INIT$_$SYSTEM'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FINALIZE$_$OBJPAS'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'INIT$_$LNFODWRF'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FINALIZE$_$LNFODWRF'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'INIT$_$FPINTRES'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FINALIZE$_$WINDIRS'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'SYSUTILS$_$TENCODING_$__$$_create'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'SYSUTILS$_$TENCODING_$__$$_destroy'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'INIT$_$SYSUTILS'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FINALIZE$_$SYSUTILS'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'INIT$_$TYPINFO'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FINALIZE$_$TYPINFO'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'INIT$_$CLASSES'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FINALIZE$_$CLASSES'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'THREADVARLIST_$SYSTEM'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'THREADVARLIST_$CLASSES'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'RESSTR_$RTLCONSTS_$$_START'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'RESSTR_$RTLCONSTS_$$_END'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'RESSTR_$SYSCONST_$$_START'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'RESSTR_$SYSCONST_$$_END'
[dcc64 Error] Project2.dpr(170): E2065 Unsatisfied forward or external declaration: 'FPC_LIBINITIALIZEUNITS' 

出于好奇,为什么你不能在Delphi中编译你的FPC代码呢?(可能有很多原因,但如果你能说一下原因,我们或许可以帮助你。)这样做可以避免整个问题,你可以完全正常地使用你的代码。 - David
1
@DavidM 更多的优化,更多的FPU选择。这就是为什么。Delphi 32位编译器有SSE3吗? - user3060326
1
如果你想要真正优化的代码,你可以写汇编语言。或者你可以使用一个好的C++编译器。FPC是否能生成高度优化的FP代码?我敢打赌英特尔C++编译器更好。 - David Heffernan
1
你需要坚持使用C风格的代码。 - David Heffernan
@DavidHeffernan 可能吧,但是 FPC 在主干中有一个 LLVM 编译器。很难超越它。 :) - user3060326
显示剩余7条评论
1个回答

8

很有可能你无法使其正常工作,至少按照原本的写法是这样。未满足的声明来自于FPC运行时库。你需要链接它,或在Delphi中重新实现它。这两个选项都不太可行。

当然,如果你删除对Classes单元的引用,并将这个简单函数放在一个单独的代码单元而不是库单元中,则有可能没有未满足的声明。话虽如此,肯定是因为你想使用真正有用的FPC代码才会探索这个问题。一旦你这样做了,你就又回到了起点。

解决这个问题的方法是动态链接FPC代码。将FPC代码编译成库并动态链接到该库。


仅出于好玩,我尝试将一个FPC对象链接到Delphi程序。FPC单元:

unit unit1;

interface

implementation

function Test(i: Integer): Integer; cdecl;
begin
  Test := i*42;
end;

end.

我使用以下命令编译:

fpc unit1.pp

然后我写了下面的Delphi程序来链接它:

{$APPTYPE CONSOLE}

{$L 'unit1.o'}

function Test(i: Integer): Integer; cdecl; 
  external name 'UNIT1_TEST$SMALLINT$$SMALLINT';

begin
  Writeln(Test(666));
end.

输出结果为:
27972
注意函数名已被修饰。为了找到名称,我使用了objdump工具:
> objdump -d unit1.o

unit1.o:    文件格式为 pe-i386
段 .text.n_unit1_test$smallint$$smallint 的反汇编:
00000000 : 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 0f bf 45 08 movswl 0x8(%ebp),%eax a: 6b c0 2a imul $0x2a,%eax,%eax d: 66 89 45 fc mov %ax,-0x4(%ebp) 11: 66 8b 45 fc mov -0x4(%ebp),%ax 15: c9 leave 16: c3 ret ...
我在x86版本的编译器上完成了这项工作。我预计在x64版本下也是可行的。
因此,您确实可以链接FPC对象文件,只要它们足够简单。但是,如果您需要FPC运行时和标准单元中的任何内容,那么我认为它将变得太难了。

您可以通过使用Delphi RTL来解决RTL问题。但我不确定是否能够编译。 - user3060326
你不能随便替换任何旧的RTL。它必须是正确的。FPC和Delphi有不同的RTL。同样,仅仅因为它们有相同的名称(RTL),并不意味着它们可以互换。 - David Heffernan
我进行了测试,就我所知,该语法尚不存在,甚至在主干中也没有。顺便问一下,这是在哪个 Delphi 版本中引入的? - Marco van de Voort
如果我没记错的话,@Marco可能是使用了过载(overloads)功能。可能是D3。这个肯定很老了。 - David Heffernan
@MarcovandeVoort 更重要的问题是为什么我们不能用Delphi链接缺失的函数?这些函数在哪里定义?是哪个“.o”文件? - user3060326
显示剩余19条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接