2011-01-09 10 views
5

Sono nuovo in Delphi. Stavo cercando di aggiungere file di oggetti C nel mio progetto Delphi e collegarli direttamente poiché Delphi supporta il collegamento di oggetti in C. Ho funzionato quando collego un singolo file Object. Ma quando provo a collegare più file oggetto, ricevo l'errore "Inoltra non inoltrata o dichiarazione esterna". Ho provato questo in Delphi 2007 e XE.So cosa sto facendo di sbagliato qui?Errore durante il collegamento di più file oggetto C in Delphi 2007

Codice lavoro: Codice

function a_function():Integer;cdecl; 

implementation 

{$Link 'a.obj'} 

function a_function():Integer;cdecl;external; 

end. 

Errore:

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

La mia ipotesi: "b_function()" o "c_function()" non si trova in nessuno dei tre file oggetto. Presumi il problema relativo al collegamento di più file oggetto e hai dimostrato di poter collegare un file. Hai provato a collegare, ad esempio, solo "b.obj" e importando solo "b_function()"? –

+0

Forse questo articolo di Rudy Velthuis potrebbe aiutare: http://rvelthuis.de/articles/articles-cobjs.html – vcldeveloper

risposta

7

Per inciso, l'articolo collegato da @vcldeveloper ha una buona spiegazione di alcuni dei problemi più comuni. Il trucco di fornire funzioni CLL mancanti nel codice Pascal è eccellente e molto più rapido rispetto al tentativo di collegare le funzioni necessarie come file C o anche come file .obj.

Tuttavia, ho il sospetto che io sappia cosa sta succedendo qui. Io uso questo stesso approccio, ma in effetti ho più di 100 file .obj nell'unità. Trovo che quando aggiungo nuovi, ottengo lo stesso errore linker come fai tu. Il modo in cui aggiro questo è provare a riordinare le mie istruzioni $ LINK. Cerco di aggiungere i nuovi file obj uno per uno e sono sempre stato in grado, infine, di aggirare questo problema.

Se i file C sono totalmente standalone, è possibile inserirne uno in un'unità diversa e il linker gestirlo. Tuttavia, dubito che sia il caso e in effetti sospetto che se fossero davvero autonomi, questo problema non si verificherebbe. Inoltre, è consigliabile avere le istruzioni $ LINK in una singola unità in modo che tutte le funzioni RTL che devono essere fornite possano essere fornite una sola volta e una sola volta (devono apparire nella stessa unità delle istruzioni $ LINK).

questa stranezza nel linker era presente in Delphi 6 ed è presente in Delphi 2010.

EDIT 1: La realizzazione è ormai venuto in mente che la questione è probabilmente a causa di Delphi utilizzando un unico compilatore passaggio . Sospetto che l'errore "riferimento esterno mancante" sia dovuto al fatto che il compilatore elabora i file obj nell'ordine in cui appaiono nell'unità.

Supponiamo che a.obj appaia prima di b.obj e tuttavia a.obj richiami una funzione in b() b.obj. Il compilatore non saprebbe dove b() risiede nel punto in cui ha bisogno di correggere la chiamata di funzione. Quando trovo il tempo, cercherò di verificare se questa ipotesi sia per lo meno plausibile!

Infine, un altro modo semplice per risolvere il problema sarebbe quello di combinare a.c, b.c e c.c in un singolo file C, che sarebbe opportuno ignorare questo problema per l'OP.

Edit 2: Ho trovato un'altra domanda Stack Overflow che copre questo terreno: stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter

Edit 3: ho trovato un altro modo veramente meraviglioso per risolvere questo problema.Ogni volta che il compilatore si lamenta

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

è sufficiente aggiungere, nella sezione implementazione del gruppo, una dichiarazione in questo modo:

procedure _a; external; 

Se si tratta di una routine che si desidera chiamare da Delphi allora si chiaramente necessario ottenere l'elenco dei parametri, chiamare le convenzioni ecc. corrette. In caso contrario, se si tratta di una routine interna al codice esterno, è possibile ignorare l'elenco dei parametri, chiamare convenzioni ecc.

Per quanto ne so, questo è l'unico modo per importare due oggetti che si riferiscono l'un l'altro in un modo circolare. Credo che dichiarare una procedura esterna in questo modo sia come fare una dichiarazione in avanti. La differenza è che l'implementazione è fornita da un oggetto piuttosto che da un codice Pascal.

Sono ora in grado di aggiungere un paio di altri strumenti alla mia armeria - grazie per aver fatto la domanda!

+0

Grazie mille. Immagino che il linker single pass sia il problema. Sto collegando oltre 30 oggetti che non sono stand-alone. Quindi dovrò riordinare i miei file oggetto o inserirli in un singolo file. – Ramnish

+0

@Ramnish Sarei interessato a sapere come vai avanti. Pedanticamente, penso che sia il compilatore che è single pass piuttosto che il linker e il mio istinto mi dice che questo è un problema di compilatore piuttosto che un problema di linker, ma sto solo indovinando a questo! –

+0

@Ramnish Ho trovato un'altra domanda di overflow dello stack che copre questo argomento: http://stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter –

0

la sintassi va bene, ma come Cosmin ha detto che è probabile che qualcosa non va con b.obj, c.obj o b_function e c_function.

Provare prima a collegarli singolarmente o modificare il proprio post per mostrare il codice effettivo e i messaggi di output del linker, se possibile.