PDA

Ver la versión completa : Colisión con los includes....



Weif Raider
23/04/2005, 20:32
Wenas... tengo un pequeño problema a la hora de compilar un juego... :(

resulta que tengo un fichero "data.h" con constantes y varias estructuras generales. Luego tengo 4 ficheros "fase1.c", "fase2.c"..... que utilizan las estructuras del fichero "data.h".

Si hago un include de "data.h" en cada uno de los ficheros de las fases me dice que los tipos están redefinidos. Si no lo hago, dice q no existen XDDD

Alguien me puede decir cómo puedo solucionar el problema?? es que metiendo el código de todas las fases en el mismo fichero sería un infierno :(

gracias!!!

Franxis
23/04/2005, 21:03
En el fichero .h pon al principio:
#ifndef MIDATA_H
#define MIDATA_H

Y al final:
#endif

Si haces varios .h, pon defines distintos para cada .h, y q no sean usados en otras partes del código...

salu2

kmkzk
23/04/2005, 21:19
Lo que yo suelo hacer para casos en los que hay que usar variables generales y cosas asi en varios modulos de codigo, es declararlos todos en un fichero '.c', y luego declararlos como 'extern' en un '.h'.
Supongo que el metodo que dice franxis es tambien valido, y seguramente mas limpio, pero no se porque yo tenia problemas al hacerlo de esa manera.
saludos

Weif Raider
23/04/2005, 21:55
Franxis, creo que no entendiste el problema o yo no me expliqué con claridad.

Tengo únicamente un fichero .h -> "data.h"

y varios ficheros .c que usan "data.h".

debería poner en cada fichero .c:

#ifndef "data.h"
#define "data.h"


Gracias!!!

kmkzk
23/04/2005, 22:09
Franxis, creo que no entendiste el problema o yo no me expliqué con claridad.

Tengo únicamente un fichero .h -> "data.h"

y varios ficheros .c que usan "data.h".

debería poner en cada fichero .c:

#ifndef "data.h"
#define "data.h"


Gracias!!!

El fichero .h deberia ser algo asi:

#ifndef _LOQUEQUIERASPONER_
#define _LOQUEQUIERASPONER_

... definiciones, estructuras...etc ...

#endif


Y luego en tus ficheros .c poner el include como siempre (#include "data.h").
Creo que seria asi :)
saludos

Weif Raider
23/04/2005, 23:27
oks!

gracias kmkzk, ya mañana lo pruebo ;)

Damizean
24/04/2005, 06:44
quizá sea también porque estas declarando alguna variable en el propio .h, si es así, declarala como extern y en alguno de los .c vuelvela a declarar. Por ejemplo

>> Cosas.h <<


#ifndef COSAS_H
#define COSAS_H

extern int supervariabledelcopon;

#endif /* COSAS_H */

>> Cosas1.c <<


#include "Cosas.h"

int supervariabledelcopon;

Weif Raider
24/04/2005, 13:03
No, en el data.h no declaro ninguna variable, únicamente constantes y estructuras que se usan en varios módulos del programa...

Por cierto, qué diferencia hay entre compilar un fichero linkandolo al compilar y hacer los includes???

Aiken
24/04/2005, 13:47
No, en el data.h no declaro ninguna variable, únicamente constantes y estructuras que se usan en varios módulos del programa...

Por cierto, qué diferencia hay entre compilar un fichero linkandolo al compilar y hacer los includes???


Normalmente se incluyen archivos .h y se linkan archivos .c por costumbre


Si haces un include los dos archivos se juntan fisicamente en el preprocesador (creo) con lo que el compilador cree que hay uno, vamos que tu eres el unico que tienes dos, para el seran uno solo.


Para ejecutables no se, pero si estas creando una libreria, luego se pueden manejar los archivos linkados dentro de la libreria, ver los que hay etc, con el comando "ar" si no recuerdo mal.


Lo dicho: Normalmente se incluyen archivos .h y se linkan archivos .c por costumbre :)

Aiken

Uncanny
24/04/2005, 19:53
Por cierto, qué diferencia hay entre compilar un fichero linkandolo al compilar y hacer los includes???
La pregunta me suena algo extraña, los includes no forman parte del proceso de linkado propiamente dicho, sino al del preprocesado, lo que supongo es que te refieres a la diferencia de compilarlos solamente y luego linkar los ficheros compilados. En C el proceso de "compilado" pasa por estas fases o pasos:

1) Preprocesado: el preprocesador procesa (valga la redundancia) todas las directivas propias del preprocesador de C que encuentra en los ficheros fuentes que se van a compilar, #includes, #defines... en busca de declaraciones de constantes, macros, variables externas y permanentes (la que ha mencionado Damizean con el uso de extern), etc, declaradas en distintos archivos de cabecera (.h) y/o fuentes (.c).

2) Compilación: una vez el preprocesado ha concluido correctamente, se pasa a procesar el codigo fuente completo y, si no encuentra errores, pasa a crear el codigo objeto (codigo máquina o binario) a partir de las fuentes. Un Ejemplo de solo preprocesado + compilación sin pasar por la fase de linkado, con GCC sería: gcc -c fichero.c (generando un fichero.o).

3) Enlazado o linkado: Es el último paso, y aquí se unen los distintos ficheros de codigo objeto que se generan en los anteriores pasos de preprocesado y compilación, creando al fin un fichero que los une a todos en uno solo (si no hablamos de compilación dinámica) capaz de ser ejecutado por la maquina y sistema operativo que se está usando (salvo que se use un compilador cruzado). Ejemplo con GCC a partir de dos ficheros previamente compilados: gcc -o programa_final_ejecutable fichero1.o fichero2.o (genera el fichero programa_final_ejecutable que su nombre ya lo dice todo).

Weif Raider
24/04/2005, 21:52
Muchas gracias por la explicación Uncanny.

Ya sé que la pregunta es rara, es que creo que no la supe expresar correctamente. Intentaré explicarlo mejor....

Me refiero a que, si en un fichero "fileA.c" haces referencia a una función que está en el fichero "fileB.c". Tienes dos opciones para ello:

1º. En el "fileA.c" metes #include "fileB.c"
2º. Los linkas y así puedes hacer referencia sin includes.

theNestruo
24/04/2005, 22:00
1º. En el "fileA.c" metes #include "fileB.c"
No hagas eso nunca. Piensa que el #include lo que va a hacer es pegar todo el fileB.c en donde esté, dentro del fileA.c, por lo que vas a duplicar código, variables, definiciones... ¡y todo ello ANTES de compilar!
Si quieres una solución "guarra" sin includes, pon el prototipo de la función de fileB.c que vas a usar dentro en fileA.c (el prototipo es la función sin cuerpo, con un ; después de cerrar el paréntesis de parámetros, vamos).
Lo que tiene que ir en un .h son precisamente los prototipos de las funciones de algún .c que se quieren hacer públicos a otros .c, los que incluyan el .h. Ni siquiera es necesario que concidan nombres ni nada parecido (puedes tener un engine.h y luego doce o trece .c diferentes para implementar las funciones que declaras en engine.h, por ejemplo).

Uncanny
24/04/2005, 22:05
resulta que tengo un fichero "data.h" con constantes y varias estructuras generales. Luego tengo 4 ficheros "fase1.c", "fase2.c"..... que utilizan las estructuras del fichero "data.h".

Si hago un include de "data.h" en cada uno de los ficheros de las fases me dice que los tipos están redefinidos. Si no lo hago, dice q no existen XDDD
Bueno, esto se me olvido comentarlo, respecto al fallo que dices que te da, no se si lo has solucionado con lo que te han dicho, pero creo que lo demás te entendieron, lo que pasa es que quizás quedo algo por explicar tanto por ti como por el resto con las soluciónes que te han dado, que por cierto, estoy de acuerdo con la que propuso en primer lugar Franxis.

Dices que tienes un header llamado data.h con constantes y estructuras declaradas y ninguna variable, dices además que data.h es declarada su inclusión dentro de cada archivo fuente (fase1.c, fase2.c, ..., faseN.c) pero lo que no has dicho es, y presupongo por el error, si estos ficheros fuentes estan al final relacionados o enlazados de alguna forma directa, es decir, si son llamadas a su vez de alguna manera por uno o varios ficheros fuentes en su declaración de inclusión (ejemplo: el fichero juego.c tiene decladado que incluya fase1.c, fase2.c, ..., faseN.c, que a su vez cada faseN.c tiene declarado que incluya data.h), como has dicho puedes obtener un error de redefinición en alguna de las declaraciones que se hacen en data.h casi con total seguridad si no ha a usado en data.h alguna directiva condicional de preprocesador en sus declaraciones de constantes y estructuras.

El error de redefinición vendría (ahora toca soltar el rollo...), basandome en lo que he dicho antes, de que como tienes data.h declarado en los ficheros faseN.c (modulos de tu programa), si incluyes y usas más de uno en otro archivo fuente, y no has usado la directiva #ifndef identificador #define identificador #endif, que viene a significar, "if not defined" o la traducción de andar por casa sería algo asi como "definir identificador SI identificador NO ha sido definido antes". En resumen, lo que hace la directiva #ifndef es condicionar el uso y definición de "identificador" (_DATA_H por ejemplo) y su contenido (definiciones/declaraciones de constantes, macros, estructuras, etc) solo SI el preprocesador no ha encontrado antes que ya ha sido definido previamente (como por ejemplo otro fichero faseN.c procesado antes que incluya también data.h) mientras ha revisado todas las directivas que ha encontrado en los ficheros fuentes que ha estado procesando, por lo que al final obtendrías un error de que alguna de esas definiciones que haces en el data.h están definidas más de una vez.

La solución a tu problema, sin saber más de tu código, parecería ser la que te ha dado Franxis y los demás (disculpad en la redundancia por el código):

// Tu fichero data.h

#ifndef _DATA_H
#define _DATA_H

// definiciones que ya tengas de constantes,
// macros, estructuras, variables externas, etc.

#endif
Hacer esto de usar condicionales en las definiciones que se encuentran dentro de archivos de cabeceras y que vas a usar en varios fuentes del programa es una buena costumbre, tengas claro al principio si vas a usarlo con uno o más o los vayas a usar como librerias propias o no, así previenes este tipo de errores de duplicación de inclusiones (variables ya definidas, redefinición de tipos, etc.) que luego dan más de un dolor de cabeza.

Weif Raider
25/04/2005, 01:45
oks, muchas gracias por las explicaciones, creo que ya me quedó todo claro.

El caso es que lo que estaba haciendo antes ya sabía que era una chapuza del 15, pero como no sabía exactamente cómo funcionaba lo del preprocesador y lo de los includes, pues así salió la cosa.

Lo que hice fue poner en el .h los #ifndef y ahora ya no me da problemas, y he quitado todos los includes "fichero.c", ya que al lincarlos al compilar, puedo usar las funciones de un módulo en otro (cosa que no sabía tampoco...).

Como parece que la cosa va más o menos bien, ya he limpiado y ordenado algo de código, me voy a meter con los gráficos... q aunq no son muy jodidos, las animaciones llevan su tiempo ;)

Franxis
25/04/2005, 02:34
Franxis, creo que no entendiste el problema o yo no me expliqué con claridad.

Tengo únicamente un fichero .h -> "data.h"

y varios ficheros .c que usan "data.h".

debería poner en cada fichero .c:

#ifndef "data.h"
#define "data.h"


Gracias!!!

Te entendí bien, y la forma de resolverlo es lo que te he dicho, modificando el .h poniendo al principio y al final lo q te puse en el post :-)