Ошибка при связывании нескольких файлов объектов C в Delphi 2007 - PullRequest
5 голосов
/ 09 января 2011

Я новичок в Delphi.Я пытался добавить файлы C Object в свой проект Delphi и связать их напрямую, поскольку Delphi поддерживает C Object Linking.Я получил это работает, когда я связываю один объектный файл.Но когда я пытаюсь связать несколько объектных файлов, я получаю сообщение об ошибке «Неудовлетворенное прямое или внешнее объявление».Я пробовал это в Delphi 2007, а также XE. Так что я здесь делаю не так?

Рабочий код:

function a_function():Integer;cdecl;  

implementation  

{$Link 'a.obj'}  

function a_function():Integer;cdecl;external;  

end.

Код ошибки:

function a_function():Integer;cdecl;  
function b_function();Integer;cdecl;  
function c_function();Integer;cdecl;  

implementation  

 {$LINK 'a.obj'}  
 {$LINK 'b.obj'}  
 {$LINK 'c.obj'}  

function a_function():Integer;cdecl;external;  
function b_function();Integer;cdecl;external;  
function c_function();Integer;cdecl;external;  
end.

1 Ответ

7 голосов
/ 09 января 2011

Кроме того, статья, на которую ссылается @vcldeveloper, содержит хорошее объяснение некоторых распространенных проблем.Уловка предоставления отсутствующих функций C RTL в коде Pascal превосходна и намного быстрее, чем попытка связать необходимые функции как файлы C или даже как файлы .obj.

Однако у меня есть подозрение, что я знаючто происходит здесь.Я использую этот же подход, но на самом деле в устройстве содержится более 100 файлов .obj.Я обнаружил, что когда я добавляю новые, я получаю ту же ошибку компоновщика, что и вы.Чтобы обойти это, попробуйте переупорядочить мои инструкции $ LINK.Я пытаюсь добавить новые файлы obj один за другим, и мне всегда удавалось, в конце концов, обойти эту проблему.

Если ваши файлы C полностью автономны, вы можете поместить каждый из них в отдельную единицу икомпоновщик справится с этим.Однако я сомневаюсь, что это так, и действительно подозреваю, что если бы они действительно были автономными, то эта проблема не возникла бы.Кроме того, желательно иметь инструкции $ LINK в одном блоке, чтобы любые функции RTL, которые должны быть предоставлены, могли предоставляться только один раз (они должны появляться в том же блоке, что и инструкции $ LINK).

Эта странность в компоновщике присутствовала в Delphi 6 и присутствует в Delphi 2010.

EDIT 1 : теперь меня осенило, что эта проблема, вероятно, связана с Delphiиспользуя однопроходной компилятор.Я подозреваю, что ошибка «отсутствует внешняя ссылка» происходит из-за того, что компилятор обрабатывает файлы .obj в том порядке, в котором они появляются в модуле.

Предположим, что a.obj появляется перед b.obj и все же a.obj вызывает функцию из b () b.obj.Компилятор не будет знать, где находится b () в той точке, где он должен исправить вызов функции.Когда я найду время, я попытаюсь проверить, является ли эта гипотеза как минимум правдоподобной!

Наконец, еще один простой выход из проблемы - это объединить ac, bc и cc в один Cфайл, который, как мне кажется, обходит эту проблему для OP.

Edit 2 : я нашел еще один вопрос переполнения стека, который охватывает это основание: stackoverflow.com / questions / 3228127 / Why-по-порядку-связанного-объект-файла-с-l-директивой-вопросом

Редактировать 3 : я нашел другой действительно замечательный способ обойтиЭта проблема.Каждый раз, когда компилятор жалуется

[DCC Error] Unit1.pas(1): E2065 Unsatisfied forward or external declaration: '_a'

, вы просто добавляете в разделе реализации модуля объявление вроде этого:

procedure _a; external;

Если это процедура, которую вы хотите вызватьот Delphi, тогда вам явно необходимо получить правильный список параметров, соглашения о вызовах и т. д.В противном случае, если это внутренняя процедура для внешнего кода, вы можете игнорировать список параметров, соглашения о вызовах и т. Д.

Насколько мне известно, это единственный способ импортировать два объекта, которые относятся к каждомудругой по кругу.Я полагаю, что объявление внешней процедуры подобным образом сродни предварительному заявлению.Разница в том, что реализация обеспечивается объектом, а не кодом Pascal.

Теперь я могу добавить еще пару инструментов в мой арсенал - спасибо, что задали вопрос!

...