2011-01-09 2 views
5

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

Рабочий код: Код

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. 
+0

Мое предположение: «b_function()» или «c_function()» не найдено ни в одном из трех объектных файлов. Вы предполагаете, что проблема связана с связыванием нескольких объектных файлов, и вы доказали, что можете связать один файл. Вы пытались связать, например, только «b.obj» и импортировать только «b_function()»? –

+0

Возможно, эта статья Руди Велтиуса могла бы помочь: http://rvelthuis.de/articles/articles-cobjs.html – vcldeveloper

ответ

7

В стороне статья, связанная с @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(), в точке, где требуется исправление вызова функции. Когда я нахожу время, я попытаюсь проверить, действительно ли эта гипотеза правдоподобна!

И, наконец, еще один простой выход из проблемы заключается в объединении a.c, b.c и c.c в один файл C, который, по моему мнению, обходит эту проблему для OP.

Edit 2: Я нашел другое переполнение стека вопрос, который покрывает эту землю: stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter

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

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

вы просто добавляете в секции реализации блока, заявление так:

procedure _a; external; 

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

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

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

+0

Большое спасибо. Я думаю, что проблема с единственным проходом. Я связываю более 30 объектов, которые не одиноки. Поэтому мне придется переупорядочить мои файлы Object или поместить их в один файл. – Ramnish

+0

@Ramnish Мне было бы интересно узнать, как вы поживаете. Педантично, я думаю, что это компилятор, а не линкера, а мои инстинкты говорят мне, что это проблема компилятора, а не проблема с компоновщиком, но я только догадываюсь об этом! –

+0

@Ramnish Я нашел еще один вопрос переполнения стека, который покрывает эту почву: http://stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter –

0

Ваш синтаксис хорошо, но, как сказал Космин, вероятно, что-то не так с b.obj, c.obj или b_function и c_function.

Попробуйте связать их индивидуально сначала или отредактируйте свое сообщение, чтобы показать фактические выходные сообщения кода и компоновщика, если это возможно.

Смежные вопросы