2011-01-09 10 views
5

Soy nuevo en Delphi. Intenté agregar archivos de objetos C en mi proyecto Delphi y vincularlos directamente, ya que Delphi admite el enlace de objetos en C. Lo tengo funcionando cuando enlace un solo archivo de objeto. Pero cuando trato de vincular múltiples archivos de objeto, obtengo el error "Declaración anticipada o externa insatisfecha". Lo he intentado en Delphi 2007 y en XE. Entonces, ¿qué estoy haciendo mal aquí?Error al enlazar varios archivos de objeto C en Delphi 2007

Código de Trabajo: Código

function a_function():Integer;cdecl; 

implementation 

{$Link 'a.obj'} 

function a_function():Integer;cdecl;external; 

end. 

error:

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

Supongo que "b_function()" o "c_function()" no se encuentra en ninguno de los tres archivos de objeto. Usted asume que el problema está relacionado con vincular múltiples archivos de objeto y demostró que puede vincular un archivo. ¿Intentó vincular, por ejemplo, solo "b.obj" y solo importó "b_function()"? –

+0

Quizás este artículo de Rudy Velthuis podría ayudar: http://rvelthuis.de/articles/articles-cobjs.html – vcldeveloper

Respuesta

7

Como un aparte, el artículo vinculado por @vcldeveloper tiene una buena explicación de algunos de los problemas comunes. El truco de proporcionar funciones C RTL faltantes en el código Pascal es excelente y mucho más rápido que intentar vincular las funciones necesarias como archivos C, o incluso como archivos .obj.

Sin embargo, tengo la sospecha de que sé lo que está sucediendo aquí. Utilizo este mismo enfoque, pero de hecho tengo más de 100 archivos .obj en la unidad. Me parece que cuando agrego nuevos, obtengo el mismo error de enlazador que tú. La forma en que lo soluciono es intentar volver a ordenar mis instrucciones de $ LINK. Trato de agregar los nuevos archivos obj uno por uno y siempre he podido, por fin, solucionar este problema.

Si sus archivos C son totalmente independientes, puede poner cada uno en una unidad diferente y el enlazador se encargará de eso. Sin embargo, dudo que ese sea el caso y de hecho sospecho que si realmente fueran independientes, entonces este problema no ocurriría. Además, es conveniente tener las instrucciones de $ LINK en una sola unidad, de modo que las funciones de RTL que deban suministrarse puedan suministrarse una sola vez (deben aparecer en la misma unidad que las instrucciones de $ LINK).

Esta singularidad en el enlazador estuvo presente en Delphi 6 y está presente en Delphi 2010.

EDIT 1: La realización ha caído en la cuenta de que este problema se debe probablemente a Delphi usando un solo pase del compilador . Sospecho que el error de "referencia externa faltante" se debe a que el compilador procesa los archivos .obj en el orden en que aparecen en la unidad.

Supongamos que a.obj aparece antes que b.obj y, sin embargo, a.obj llama a una función en b() b.obj. El compilador no sabría dónde b() reside en el punto donde necesita reparar la llamada a la función. Cuando encuentre el tiempo, intentaré probar si esta hipótesis es al menos plausible.

Finalmente, otra forma fácil de resolver el problema sería combinar a.c, b.c y c.c en un único archivo C, lo que creo que evitaría este problema para el OP.

Editar 2: He encontrado otra pregunta desbordamiento de pila que cubre esta planta: stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter

Datos 3: He encontrado otra manera verdaderamente maravillosa para evitar este problema.Cada vez que el compilador se queja

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

simplemente hay que añadir, en la sección de implementación de la unidad, una declaración así:

procedure _a; external; 

Si se trata de una rutina que desea llamar desde Delphi entonces claramente es necesario que la lista de parámetros, las convenciones de llamada, etc. sean correctas. De lo contrario, si se trata de una rutina interna del código externo, puede ignorar la lista de parámetros, las convenciones de llamadas, etc.

Según mi leal saber y entender, esta es la única forma de importar dos objetos que se refieren entre sí en de una manera circular. Creo que declarar un procedimiento externo de esta manera es similar a hacer una declaración directa. La diferencia es que la implementación es provista por un objeto en lugar del código Pascal.

Ahora he podido agregar un par de herramientas más a mi arsenal: ¡gracias por hacer la pregunta!

+0

Muchas gracias. Supongo que el enlazador de pase único es el problema. Estoy vinculando más de 30 objetos que no son independientes. Así que tendré que reordenar mis archivos Object o ponerlos en un solo archivo. – Ramnish

+0

@Ramnish Me gustaría saber cómo te va. Pedaginariamente, creo que es el compilador el único que pasa en lugar del vinculador y mis instintos me dicen que esto es un problema de compilación en lugar de un problema con los enlazadores, ¡pero solo estoy adivinando esto! –

+0

@Ramnish Encontré otra pregunta sobre el Desbordamiento de pila que cubre este terreno: http://stackoverflow.com/questions/3228127/why-does-the-order-of-linked-object-file-with-l-directive-matter –

0

Su sintaxis está muy bien, pero al igual que Cosmin dijo que es probable que algo está mal con b.obj, c.obj o b_function y c_function.

Intente vincularlos individualmente primero o edite su publicación para mostrar el código real y los mensajes de salida del vinculador si es posible.

Cuestiones relacionadas