5

我是德尔福的新手。我试图在我的 Delphi 项目中添加 C 对象文件并直接链接它们,因为 Delphi 支持 C 对象链接。当我链接一个对象文件时,我得到了它的工作。但是当我尝试链接多个目标文件时,我收到错误“不满意的转发或外部声明”。我在 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.
4

1 回答 1

8

顺便说一句,@vcldeveloper 链接的文章很好地解释了一些常见问题。在 Pascal 代码中提供缺失的 C RTL 函数的技巧非常好,而且比尝试将必要的函数链接为 C 文件甚至是 .obj 文件要快得多。

但是,我怀疑我知道这里发生了什么。我使用相同的方法,但实际上单元中有 100 多个 .obj 文件。我发现当我添加新的时,我得到了和你一样的链接器错误。我解决这个问题的方法是尝试重新订购我的 $LINK 指令。我尝试一个一个地添加新的 obj 文件,我总是能够最终解决这个问题。

如果您的 C 文件是完全独立的,那么您可以将每个文件放在不同的单元中,链接器会处理它。但是,我怀疑情况是否如此,而且我确实怀疑如果它们真的是独立的,那么这个问题就不会发生。此外,最好将 $LINK 指令放在一个单元中,这样任何需要提供的 RTL 函数都可以只提供一次(它们需要与 $LINK 指令出现在同一单元中)。

链接器中的这种奇怪之处存在于 Delphi 6 中,并且存在于 Delphi 2010 中。

编辑 1:我现在意识到这个问题可能是由于 Delphi 使用了单遍编译器。我怀疑“缺少外部引用”错误是因为编译器按照它们在单元中出现的顺序处理 .obj 文件。

假设 a.obj 出现在 b.obj 之前,而 a.obj 调用 b() b.obj 中的函数。编译器不知道 b() 位于它需要修复函数调用的位置。当我找到时间时,我会尝试测试这个假设是否至少是合理的!

最后,解决这个问题的另一个简单方法是将 ac、bc 和 cc 组合到一个 C 文件中,我相信这会绕过 OP 的这个问题。

编辑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 调用的例程,那么您显然需要正确获取参数列表、调用约定等。否则,如果它是外部代码内部的例程,那么您可以忽略参数列表、调用约定等。

据我所知,这是导入两个以循环方式相互引用的对象的唯一方法。我认为以这种方式声明外部程序类似于进行前向声明。不同之处在于实现是由对象而不是 Pascal 代码提供的。

我现在已经能够在我的军械库中添加更多工具 - 感谢您提出这个问题!

于 2011-01-09T10:11:51.840 回答