Linking FPC .o files into Delphi

▼魔方 西西 提交于 2019-12-22 07:57:10

问题


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' 

回答1:


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.



来源:https://stackoverflow.com/questions/22041506/linking-fpc-o-files-into-delphi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!