Связывание файлов FPC .o с Delphi

Как связать 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' 

person user3060326    schedule 26.02.2014    source источник
comment
Ради интереса, почему вы не можете скомпилировать свой код FPC в Delphi? (Существует ряд возможных причин, но если вы можете опубликовать, почему мы могли бы помочь.) Это позволит избежать всей этой проблемы, и вы сможете использовать свой код совершенно нормально.   -  person David    schedule 26.02.2014
comment
@DavidM Больше оптимизаций, больше вариантов FPU. Вот почему. Есть ли в 32-битном компиляторе Delphi SSE3?   -  person user3060326    schedule 26.02.2014
comment
@user3060326 user3060326 Если вам нужен действительно оптимизированный код, вы можете написать asm. Или вы можете использовать хороший компилятор C++. Создает ли FPC высокооптимизированный код FP? Бьюсь об заклад, компилятор Intel C++ лучше.   -  person David Heffernan    schedule 26.02.2014
comment
Вариант @DavidHeffernan C++ возможен, но маловероятен.   -  person user3060326    schedule 26.02.2014
comment
Вам придется придерживаться кода стиля C   -  person David Heffernan    schedule 26.02.2014
comment
@DavidHeffernan Возможно, но у FPC есть компилятор LLVM в багажнике. Трудно победить это. :)   -  person user3060326    schedule 27.02.2014
comment
@user3060326 user3060326 LLVM регулярно превосходит другие компиляторы   -  person David Heffernan    schedule 27.02.2014
comment
@DavidHeffernan Нравится 32-разрядная версия Delphi XE5? Он генерирует код из 99-х годов. Pentium 386   -  person user3060326    schedule 27.02.2014
comment
Pentium 586 FWIW. Что ж, я не думаю, что какой-либо компилятор Delphi превзойдет LLVM! Мы могли бы дать больше советов, если бы знали вашу проблему. Чтобы заработать на жизнь, я пишу код с плавающей запятой, где важна производительность. Многие другие завсегдатаи здесь знают о производительности. Возможно, у нас есть несколько ценных советов, которыми мы можем поделиться.   -  person David Heffernan    schedule 27.02.2014
comment
Обратите внимание, что сторонний компилятор, использующий LLVM, автоматически находится на том же уровне, что и CLang.   -  person Marco van de Voort    schedule 01.03.2014
comment
@MarcovandeVoort Не совсем корректное сравнение. Clang производит лучший код, чем FPC.   -  person user3060326    schedule 01.03.2014
comment
Мой комментарий был неправильным, он должен был сказать .... автоматически НЕ находится на том же уровне, что и CLang.   -  person Marco van de Voort    schedule 02.03.2014


Ответы (1)


Крайне маловероятно, что вы сможете сделать эту работу, по крайней мере, как написано. Неудовлетворенные объявления относятся к среде выполнения FPC. Вам также нужно связать это или повторно реализовать в Delphi. Ни один из вариантов не является жизнеспособным.

Конечно, если вы удалите ссылку на модуль Classes и поместите эту простую функцию в отдельный модуль кода, а не в библиотечный модуль, вполне вероятно, что неудовлетворенных объявлений не будет. Тем не менее, вы наверняка изучаете это, потому что хотите использовать код FPC, который действительно что-то делает. И как только вы это сделаете, вы вернетесь к исходной точке.

Выход из этой проблемы — динамическая ссылка на код FPC. Скомпилируйте код FPC в библиотеку и динамически свяжите эту библиотеку.


Ради интереса я попытался связать объект FPC с программой Delphi. Блок ФПК:

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:     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
        ...

Я проделал эту работу с версиями компилятора x86. Я ожидаю, что это жизнеспособно и под x64.

Таким образом, вы действительно можете связать объектные файлы FPC, если они достаточно просты. Однако, если вам понадобится какая-либо среда выполнения FPC и стандартные модули, я ожидаю, что это станет слишком сложно.

person David Heffernan    schedule 26.02.2014
comment
Вы можете обойти проблему RTL, используя Delphi RTL. Но я не уверен, что это скомпилируется. - person user3060326; 26.02.2014
comment
Вы не можете просто заменить любой старый RTL. Он должен быть правильным. FPC и Delphi имеют разные RTL. Опять же, из того, что они имеют одинаковое имя (RTL), не следует, что они взаимозаменяемы. - person David Heffernan; 26.02.2014
comment
Большие проблемы возникнут, когда вы попытаетесь использовать более сложные типы. Или даже использовать их в качестве параметров/возвращаемых значений для ваших экспортируемых функций. Типы, отличные от стандартных типов взаимодействия C (целочисленные типы, типы с плавающей запятой, указатели), не могут использоваться через границы взаимодействия. Я знаю, что Реми и я сказали вам это в ответ на ваш предыдущий вопрос, и вы, кажется, нам не поверили. Но это правда. - person David Heffernan; 26.02.2014
comment
А как насчет System.pas? Вы имеете в виду системный блок Delphi? Это бесполезно для любого кода FPC. - person David Heffernan; 26.02.2014
comment
Можно установить неискаженное имя для символа, добавив [public,alias:'namethatyoulike']; после соглашения о вызовах. О, и системный блок FPC - это system.pp, но, конечно, вы правы. - person Marco van de Voort; 28.02.2014
comment
@Marco Можете ли вы сделать это для перегруженной функции или они не подлежат экспорту? Смотрите более свежий вопрос, на который я ответил. Вполне возможно неправильно. Кроме того, на что похож кодген FPC? Выдает ли он эффективный код? - person David Heffernan; 28.02.2014
comment
Да, на самом деле у вас могут быть две перегруженные функции с разными идентификаторами уровня компоновщика. Но оператор экспорта afaik принимает уровень паскаля, а не идентификаторы уровня компоновщика. - person Marco van de Voort; 28.02.2014
comment
@Marco Это означает, что мой ответ здесь (stackoverflow.com/ вопросов/22068653/) точно? - person David Heffernan; 28.02.2014
comment
Я проверил, и насколько я вижу, такого синтаксиса еще не существует, даже в транке. Кстати, какая версия Delphi была представлена? - person Marco van de Voort; 28.02.2014
comment
@Marco Пришел с перегрузками IIRC. Д3 возможно. Конечно он старый. - person David Heffernan; 28.02.2014
comment
@MarcovandeVoort Более важный вопрос: почему мы не можем связать недостающие функции с Delphi? Где они определены? Который 1_? - person user3060326; 28.02.2014
comment
Вы не сможете связать их. Марко согласился со мной в своем первом комментарии. - person David Heffernan; 28.02.2014
comment
Простая причина заключается в том, что для кода FPC требуется среда выполнения FPC, а для кода Delphi требуется среда выполнения Delphi. Это нормально. MSVC++ также не может использовать предварительно скомпилированную стандартную библиотеку C++ GCC. - person Marco van de Voort; 28.02.2014
comment
@MarcovandeVoort Правда. Но, по крайней мере, мы можем связать C объект, но не можем связать FPC. Настоящее разочарование. - person user3060326; 28.02.2014
comment
@user Вы можете связать объекты FPC. Мой ответ демонстрирует это. - person David Heffernan; 28.02.2014
comment
Как только вы начнете использовать среду выполнения, вы, возможно, перестанете использовать C. Как вы можете видеть на примере Дэвида. В C это не так сильно вас ограничивает, так как нет ни языка, ни среды выполнения. На уровне дельфийского диалекта это просто более заметно. - person Marco van de Voort; 28.02.2014
comment
Да, @Marco совершенно прав. Как только вы начнете использовать функции ООП, вы обнаружите, что вам нужна полная поддержка во время выполнения. Таким образом, придерживаться очень простого кода в стиле C будет нормально. - person David Heffernan; 28.02.2014
comment
Что ж, C afaik теперь тоже имеет int64. Используйте его, скомпилируйте с помощью GCC, и он начнет придираться к libgcc. (и на простом уровне Pascal также такие вещи, как наборы › 32 элемента, stings и динамические массивы имеют помощники) - person Marco van de Voort; 28.02.2014
comment
@MarcovandeVoort Все отлично и денди. Но GCC или ICC будут генерировать лучший код. - person user3060326; 28.02.2014
comment
@user Лучше чего? Делфи или ФПК? - person David Heffernan; 28.02.2014
comment
@DavidHeffernan Оба. - person user3060326; 28.02.2014
comment
@user В таком случае, почему вы пытаетесь использовать FPC, а не gcc или icc? А какое приложение, из интереса? - person David Heffernan; 28.02.2014
comment
user3060326: Я не понимаю, как производительность FPC относительно icc или нет имеет какое-либо отношение к этому обсуждению, которое касается связывания и совместимости связывания. - person Marco van de Voort; 01.03.2014
comment
@user Я вижу, что ты не принял ответ. Это почему? Как вы думаете, я ошибаюсь? - person David Heffernan; 01.03.2014