How can I link a FPC .o
from a library to a Delphi executable. When I try to link the following code I get a bunch of unsatisfied forward or external declarations.
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'
It is highly unlikely that you will be able to make this work, at least as written. The unsatisfied declarations are from the FPC runtime. You'd need to link that too, or re-implement it in Delphi. Neither option is terribly viable.
Of course, if you removed the reference to the Classes
unit, and put this simple function in separate code unit rather than a library unit then it is plausible that there might be no unsatisfied declarations. That said, surely you are exploring this because you want to use FPC code that actually does something. And as soon as you do that, then you will be right back to square one.
The way out of this problem is to link to the FPC code dynamically. Compile the FPC code into a library and link to that library dynamically.
Just for fun I tried to link an FPC object to a Delphi program. The FPC unit:
unit unit1;
interface
implementation
function Test(i: Integer): Integer; cdecl;
begin
Test := i*42;
end;
end.
I compiled this with:
fpc unit1.pp
Then I wrote the following Delphi program to link it:
{$APPTYPE CONSOLE}
{$L 'unit1.o'}
function Test(i: Integer): Integer; cdecl;
external name 'UNIT1_TEST$SMALLINT$$SMALLINT';
begin
Writeln(Test(666));
end.
The output:
27972
Note that the function name is decorated. In order to find the name I used objdump
:
>objdump -d unit1.o unit1.o: file format pe-i386 Disassembly of section .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 ...
I did this work with x86 versions of the compiler. I expect that it's viable under x64 too.
So you can indeed link FPC object files, provided that they are simple enough. However, should you need any of the FPC runtime and standard units, then I expect it will become too hard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With