Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error While Linking Multiple C Object files in Delphi 2007

I am new to delphi. I was trying to add C Object files in my Delphi project and link them directly since Delphi Supports C Object Linking. I got it working when i link a single Object file. But when i try to link multiple object files, i am getting error 'Unsatisfied forward or external declaration'. I have tried this in Delphi 2007 as well as XE.So what am i doing wrong here?

Working Code:

function a_function():Integer;cdecl;  

implementation  

{$Link 'a.obj'}  

function a_function():Integer;cdecl;external;  

end.

Error Code:

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.
like image 574
Ramnish Avatar asked Jan 09 '11 07:01

Ramnish


1 Answers

As an aside, the article linked by @vcldeveloper has a good explanation of some of the common issues. The trick of providing missing C RTL functions in Pascal code is excellent and much quicker than trying to link in the necessary functions as C files, or even as .obj files.

However, I have a suspicion that I know what is going on here. I use this same approach but in fact have over 100 .obj files in the unit. I find that when I add new ones, I get the same linker error as you do. The way I work around this is to try re-ordering my $LINK instructions. I try to add the new obj files one by one and I have always been able, eventually, to get around this problem.

If your C files are totally standalone then you could put each one in a different unit and the linker would handle that. However, I doubt that is the case and indeed I suspect that if they really were standalone then this problem would not occur. Also, it's desirable to have the $LINK instructions in a single unit so that any RTL functions that need to be supplied can be supplied once and once only (they need to appear in the same unit as the $LINK instructions).

This oddity in the linker was present in Delphi 6 and is present in Delphi 2010.

EDIT 1: The realisation has now dawned on me that this issue is probably due to Delphi using a single pass compiler. I suspect that the "missing external reference" error is because the compiler processes the .obj files in the order in which they appear in the unit.

Suppose that a.obj appears before b.obj and yet a.obj calls a function in b() b.obj. The compiler wouldn't know where b() resides at the point where it needs to fixup the function call. When I find the time, I going to try and test if this hypothesis is at the very least plausible!

Finally, another easy way out of the problem would be to combine a.c, b.c and c.c into a single C file which would I believe bypass this issue for the OP.

Edit 2: I found another Stack Overflow question that covers this ground: stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter

Edit 3: I have found another truly wonderful way to work around this problem. Every time the compiler complains

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

you simply add, in the implementation section of the unit, a declaration like so:

procedure _a; external;

If it is a routine that you wish to call from Delphi then you clearly need to get the parameter list, calling conventions etc. correct. Otherwise, if it is a routine internal to the external code, then you can ignore the parameter list, calling conventions etc.

To the best of my knowledge this is the only way to import two objects that refer to each other in a circular manner. I believe that declaring an external procedure in this way is akin to making a forward declaration. The difference is that the implementation is provided by an object rather than Pascal code.

I've now been able to add a couple of more tools to my armory – thank you for asking the question!

like image 110
6 revs Avatar answered Sep 18 '22 05:09

6 revs