Ayuda, por favor, con algo muy básico - Compilación (SOLUCIONADO)

Iniciado por mariyop, 8 Agosto 2011, 10:10 AM

0 Miembros y 2 Visitantes están viendo este tema.

mariyop

Buenos días a todos!

Sé que mi pregunta es muy básica, pero he estado buscando información al respecto y no doy con la solución. Así que agradecería toda la ayuda que me puedan brindar.

Trabajo en Ubuntu y he escrito un programa en C, con el que debo usar dos archivos de cabecera propios (los dos primeros que aparecen).

#include "cuenta.h"
#include "opt.h"
#include <cblas.h>
#include <clapack.h>

Lo estoy intentando compilar así:
gcc Test.c -o Test -lblas -llapack
pero aparecen varios mensajes de "undefined reference to ...", todos ellos haciendo referencia a funciones de los .h que he creado.
¿Debo hacer algo al compilar para que se tengan en cuenta mis cabeceras, al igual que hago con las de Blas y Lapack? Todos los archivos están en el mismo directorio.

Muchas gracias y perdonad mi ignorancia

Ferno

¿Podrías postear el code de los .h? Quizás el problema está ahí!

Triper0

Tendrías que poner el código porque no se entiende...
Si tenes varios .c, lo mejor sería:

gcc -o ejecutable *.c -Wall

con eso te va a tomar todos los .c que tengas y va a compilar de diez.

kiriost

si colocas el nombre de los archivos de cabecera estos deben estar en la misma ruta o carpeta que el código que deseas compilar.  ::)
http://www.godsys.com.ar > Programación. Hacking y Cracking. Sistemas. Desarrollo Web.
Java, C/C++, PHP, Python, Perl, HTML, Game-Hacking, Defacing, Desarrollo Web, GNU/Linux, y más

mariyop

Podría colocar el código de los .h, pero es que es súuuuuuuuuper larguísimo. ¿Se puede poner de algún modo para que no ocupe tantísimo?

Entiendo que con mi explicación no lo entendáis muy bien, XD. Muchas gracias a todos por la ayuda.

Triper0

Cita de: mmarmm en 12 Agosto 2011, 19:45 PM
Podría colocar el código de los .h, pero es que es súuuuuuuuuper larguísimo. ¿Se puede poner de algún modo para que no ocupe tantísimo?

Entiendo que con mi explicación no lo entendáis muy bien, XD. Muchas gracias a todos por la ayuda.


Lo fundamental que tenes que saber es lo siguiente:

Los .h (headers) contienen las CABECERAS de las funciones y también las estructuras (struct, union, etc).
En los .c respectivos a esos headers, tenes que poner la implementación de las cabeceras, y no te olvides, de incluir los headers, porque por ej, si vos en un header definís una estructura, y después en el .c de ese header, la usás y no incluíste el .h, no va a funcionar.

Otro dato importante es una macro que se usa para evitar problemas de inclusión del mismo header en un archivo

#ifndef _HEADER
#define _HEADER

IMPLEMENTACIÓN del .C

#endif

Eso también es importante, más que nada cuando son programas extensos.

Bueno, está de más decir que los .h tenes que incluirlos en el main.

Ahora lo importante es la compilación. Vos tenes que compilar todos los .c, en este caso, supongamos que es A.h A.c, B.h, B.c, main.c

sería

gcc -o programa.exe main.c a.c b.c -Wall

Imaginate si tenes 800.h con sus respectivos c... ¿Medio largo no?

Bueno, entonces hacemos

gcc -o programa.exe *.c -Wall y te incluye todo por arte de magia

Ahora bien, acordate de también tener todos los archivos en la misma carpeta, porque si vos los incluís de la forma "asd.h" quiere decír que está en la misma carpeta

Creo que con esto se te va a solucionar el problema, aunque realmente no sé qué es lo que queres preguntar.

En el caso que esto no te sirva de nada, lo mejor sería que pongas el código y ahí nos vamos a dar cuenta más fácil...

Saludos!

mariyop

#6
Os pongo el código, pero como es muy extenso voy a eliminar partes que creo que no son las conflictivas (definición de variables, bucles y cosas así donde no aparezcan estas funciones problemáticas). Os pondré sólo las partes que hacen referencia a las funciones que me dan error para no ocupar tanto sitio. Esto es lo que sale al compilar con el comando que os puse en el primer comentario:

/home/mmar/PFC_linux/QP_Lapack/Test_QP.o
||In function `obtener_matrices_file.6144':|
Test_QP.c:(.text+0x2000)||undefined reference to `read_from_file'
/home/mmar/PFC_linux/QP_Lapack/Test_QP.o||In function `mpQP2':
Test_QP.c:(.text+0x5334)||undefined reference to `resolver'
Test_QP.c:(.text+0x5350)||undefined reference to `INV'
Test_QP.c:(.text+0x5486)||undefined reference to `INV'
Test_QP.c:(.text+0x55cb)||undefined reference to `max_vec'
Test_QP.c:(.text+0x568f)||undefined reference to `vertcat'
Test_QP.c:(.text+0x577a)||undefined reference to `max_vec'
Test_QP.c:(.text+0x5896)||undefined reference to `vertcat'
Test_QP.c:(.text+0x58cd)||undefined reference to `max_vec'
Test_QP.c:(.text+0x58dd)||undefined reference to `norm_vec'
Test_QP.c:(.text+0x58ed)||undefined reference to `norm_vec'
Test_QP.c:(.text+0x5a68)||undefined reference to `vertcat'
Test_QP.c:(.text+0x5a75)||undefined reference to `norm_vec'
/home/mmar/PFC_linux/QP_Lapack/Test_QP.o||In function `main':
Test_QP.c:(.text+0x6243)||undefined reference to `read_from_file'
||=== Build finished: 14 errors, 0 warnings ===


Y éste es el código de los archivos:

TEST_QP.C

#include "math_modif.h"
#include "QP2.h"
#include <cblas.h>
#include <clapack.h>

void History_init(void);
void Save_History(REAL *,REAL *,REAL *,REAL *);
void Close_History(void);

int iterac;    

int main()
{

(código omitido)

read_from_file("CtrlMPCSec.mpc");

CREAMAT(Cmat.h,FILMAT(Cmat.H),1);      /* h */
if (Cmat.G!=NULL){CREAMAT(Cmat.g,FILMAT(Cmat.G),1);}      /* g */
if (Cmat.F!=NULL){CREAMAT(Cmat.f,FILMAT(Cmat.F),1);}      /* f */

#ifdef QP2_H_
       SET_Vqp2();
#endif

#ifdef QP1_H_
       SET_Vqp1();
#endif

(código omitido)

History_init();
iterac=0;
while(exit)
{
(código omitido)

#ifdef QP2_H_
mpQP2();
incl_mat(Cmat.U,Vqp2.uk,1,1,1,(int)FILMAT(Cmat.U),1,1);  
/* uk=uF(1:nu); */
#endif

(código omitido)
}
}


QP2.h

#ifndef QP2_H_
#define QP2_H_

void mpc2(REAL *,REAL *,REAL *,REAL *,REAL *);
void mpc3(REAL *,REAL *,REAL *,REAL *);
void SET_Vqp2(void);
void mpQP2(void);
void GR_QP2(REAL,int);
void JAC_QP2(REAL);
void EV_QP2(REAL);

(código omitido)

void mpQP2()
{

(código omitido)

while (t<(nri/(TolSol*gamma_t)))
{

(código omitido)

if (Cmat.F==NULL)
{
resolver(Vqp2.Vjac.JAC,Vqp2.Vgrad._GRAD,Vqp2.pduk);
}
else
{
/* Obtencion del dlambdak */
INV(Vqp2.Vjac.JAC,Vqp2.JAC_1);
traspuesta(Cmat.F,Vqp2.Ft);      
(código omitido)

}

multmat(Cmat.G,Vqp2.uk,Vqp2.Vmax);
resmat(Vqp2.Vmax,Vqp2.Vmax,Cmat.g);
max=max_vec(Vqp2.Vmax);

(código omitido)

if (Cmat.F==NULL)
{
copiar(Vqp2.Vgrad.GRAD,Vqp2.rt);
}
else
{               
resmat(Vqp2.F_uk_f,Vqp2.F_uk,Cmat.f);
sumamat(Vqp2._GradFtlambda,Vqp2.Vgrad.GRAD,Vqp2.F_lambdak);
vertcat(Vqp2._GradFtlambda,Vqp2.F_uk_f,Vqp2.rt);
}
(código omitido)
}


MATH_MODIF.H

#ifndef MATH_MODIF_H_
#define MATH_MODIF_H_

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <cblas.h>
#include <clapack.h>

void sumamat(REAL*,REAL*,REAL*);
void resmat(REAL*,REAL*,REAL*);
void nummat(REAL*,REAL*,REAL);
void ones(REAL,REAL,REAL*);
void zeros(REAL,REAL,REAL*);
void ones2(int ,int ,int ,int,REAL *);
void zeros2(int ,int ,int ,int ,REAL *);
void diag(REAL,REAL,REAL,REAL*);
void diagonal(REAL *,REAL,REAL*);
void traspuesta(REAL*,REAL*);
void traspuesta2(REAL *,REAL *);
void bloq(REAL*,REAL*,REAL*);
void multmat(REAL*,REAL*,REAL*);
void copiar(REAL*,REAL*);
void cholesky(REAL*,REAL*);
void sustinf (REAL*,REAL*,REAL*);
void sustsup (REAL*,REAL*,REAL*);
void resolver(REAL*,REAL*,REAL*);
int incl_mat(REAL *,REAL *,int ,int ,int ,int ,int ,int);
void INV(REAL *,REAL *);
void vertcat(REAL *,REAL *,REAL *);
void horztcat(REAL *,REAL *,REAL *);
REAL max_vec(REAL *);
REAL norm_vec(REAL *);
void eye(REAL, REAL *);
double timeval_diff(struct timeval *, struct timeval *);
int dgetrf_(int *, int *, double *, int *, int *, int *);
int dgetri_(int *, double *, int *, int *, double *, int *, int *);
int dpotrf_(char *, int *, double *, int *, int *);
int dpotrs_(char *, int *, int *, double *, int *, double *, int *, int *);

REAL *obtener_matrices_manual(void);
void obtener_matrices_file(void);
void show_matriz(char *,REAL *);
void show_matriz_2(char *,REAL *,int,int,int,int);
void read_from_file(char *);

void resolver(REAL *mat,REAL *vec,REAL *presul)
{
   int info;
   char uplo='L';
   int filas=(int)FILMAT(mat);
   int filas2=(int)FILMAT(presul);
   int columnas2=(int)COLMAT(presul);

   copiar (vec, presul);
   info=dpotrs_ (&uplo,&filas,&columnas2, (mat+2), &filas,(presul+2), &filas2, &info);

   if (info<0)
   {
      printf ("dpotrs: El argumento %d tiene un valor no válido\n", (-1)*info);
   }
}


void vertcat(REAL *mat1,REAL *mat2,REAL *presul)
{

   if (presul==mat1)
   {
      REAL *aaa;
      CREAMAT(aaa,(int)(FILMAT(mat1)+FILMAT(mat2)),(int)COLMAT(mat1));
      zeros(FILMAT(aaa),COLMAT(aaa),aaa);

      incl_mat(aaa,mat1,1,1,1,(int)FILMAT(mat1),1,(int)COLMAT(mat1));                     /* introducimos la primera--> mat1*/
      incl_mat(aaa,mat2,((int)FILMAT(mat1)+1),1,1,(int)FILMAT(mat2),1,(int)COLMAT(mat2)); /* introducimos la primera--> mat2*/

      copiar(aaa,presul);
      DESTMAT(aaa);
   }
   else
   {
   FILMAT(presul)=FILMAT(mat1)+FILMAT(mat2);
   COLMAT(presul)=COLMAT(mat1);
   zeros(FILMAT(presul),COLMAT(presul),presul);

   incl_mat(presul,mat1,1,1,1,(int)FILMAT(mat1),1,(int)COLMAT(mat1));                      /* introducimos la primera--> mat1*/
   incl_mat(presul,mat2,((int)FILMAT(mat1)+1),1,1,(int)FILMAT(mat2),1,(int)COLMAT(mat2));  /* introducimos la primera--> mat2*/
   }
}

REAL max_vec(REAL *vec)

{
   int i,j;
   REAL max;
   max=LEEMAT(vec,0,0);

   for (i=0;i<FILMAT(vec);i++)
   {
      for(j=0;j<COLMAT(vec);j++)
      {
         if (max<LEEMAT(vec,i,j))
         {
            max=LEEMAT(vec,i,j);
         }

      }
   }
   return (max);
}


void INV(REAL *A,REAL *A_1)
{

   int info;
   int info2;
   int filas=(int)FILMAT(A_1);
   int columnas=(int)COLMAT(A_1);
   int lda=(int)FILMAT(A_1);
   int *ipiv = (int *)malloc((filas)*sizeof(int));
   int lwork=(int)FILMAT(A_1);
   double work [lwork];

   copiar (A, A_1);

   //Calcula la descomposición LU de la matriz
   info=dgetrf_ (&filas, &columnas, (A_1+2), &lda, ipiv, &info);
   if (info<0)
   {
      printf ("dgetrf: El argumento %d tiene un valor no válido\n", (-1)*info);
   }else {
      if (info >0){
         printf ("dgetrf: El elemento U(%d,%d) es exactamente cero\n", info, info);
      }
   }


   //Calcula la inversa a partir de la descomposicón LU
   info2=dgetri_ (&columnas, (A_1+2), &lda, ipiv, work, &lwork, &info2);

   if (info2<0)
   {
      printf ("dgetri: El argumento %d tiene un valor no válido\n", (-1)*info);
   }else {
      if (info2>0){
         printf ("dgetri: El elemento U(%d,%d) es exactamente cero. No se pudo calcular la inversa\n", info, info);
      }
   }
}


void read_from_file(char *dir_complet)
{
   FILE *fp;
   REAL n_mat;
   int pi,pj,pk;
   char nombre[80];
   REAL filas;
   REAL columnas;
   REAL *vect;

   vect=NULL;

   printf("Abrindo : %s ...",dir_complet);
   fflush(stdout);

   if((fp=fopen(dir_complet,"r"))==NULL){
      perror (NULL);
      exit (EXIT_FAILURE);}

   fscanf(fp,"%lf",&n_mat);
   for(pk=0;pk<(int)n_mat;pk++)
   {
   fscanf(fp,"%s",nombre);
   fscanf(fp,"%lf",&filas);
   fscanf(fp,"%lf",&columnas);

   vect=NULL;

   if(!strcmp("A",nombre)) {CREAMAT(Cmat.A,filas,columnas);vect=Cmat.A;}
   else if(!strcmp("B",nombre)) {CREAMAT(Cmat.B,filas,columnas);vect=Cmat.B;}
   else if(!strcmp("C",nombre)) {CREAMAT(Cmat.C,filas,columnas);vect=Cmat.C;}
   else if(!strcmp("D",nombre)) {CREAMAT(Cmat.D,filas,columnas);vect=Cmat.D;}
   else if(!strcmp("Np",nombre)) {CREAMAT(Cmat.Np,filas,columnas);vect=Cmat.Np;}
   else if(!strcmp("F1",nombre)) {CREAMAT(Cmat.F1,filas,columnas);vect=Cmat.F1;}
   else if(!strcmp("F2",nombre)) {CREAMAT(Cmat.F2,filas,columnas);vect=Cmat.F2;}
   else if(!strcmp("H",nombre)) {CREAMAT(Cmat.H,filas,columnas);vect=Cmat.H;}
   else if(!strcmp("G",nombre)) {CREAMAT(Cmat.G,filas,columnas);vect=Cmat.G;}
   else if(!strcmp("g1",nombre)) {CREAMAT(Cmat.g1,filas,columnas);vect=Cmat.g1;}
   else if(!strcmp("g2",nombre)) {CREAMAT(Cmat.g2,filas,columnas);vect=Cmat.g2;}
   else if(!strcmp("F",nombre)) {CREAMAT(Cmat.F,filas,columnas);vect=Cmat.F;}
   else if(!strcmp("f1",nombre)) {CREAMAT(Cmat.f1,filas,columnas);vect=Cmat.f1;}
   else if(!strcmp("f2",nombre)) {CREAMAT(Cmat.f2,filas,columnas);vect=Cmat.f2;}
   else if(!strcmp("Lm",nombre)) {CREAMAT(Cmat.Lm,filas,columnas);vect=Cmat.Lm;}
   else if(!strcmp("Km",nombre)) {CREAMAT(Cmat.Km,filas,columnas);vect=Cmat.Km;}

   if (vect!=NULL){
               vect=vect+2;
                  for(pi=0;pi<filas;pi++)
                        {
                           for (pj=0;pj<columnas;pj++)
                                 {
                                    fscanf(fp,"%lf",vect);
                                    vect=vect+1;
                                 }
                        }
               }
   }
}




REAL norm_vec(REAL *vec)
{
   REAL norma;
   norma = cblas_dnrm2 ((ENTERO)FILMAT(vec), (vec+2), 1.0);
   return (norma);
}


---------------------------------

Es un programa para trabajar con matrices. Antes estaba hecho completamente "a mano", programando todas las funciones nosotros mismos, pero hemos decidido usar las librerías matemáticas de Lapack y Blas, que son más rápidas. El caso es que con la implementación "a mano" el código funciona, pero al usar las funciones de Lapack me da los errores que os he indicado. Por eso creo que me falla algo al compilar. Los cambios que he hecho los he ido probando uno a uno en ficheros aparte, con ejemplos más simples, y funcionan bien. Pero al sustituirlos aquí es donde fallan. Por eso creo que me falta algo en el código para enlazarlo todo bien.

Espero que con los trozos de código que he puesto os sirva. Muchas gracias a todos por la ayuda.

Ferno

En los .h solo va el prototipo de la función.
La implementación se hace en los .c correspondientes! La implementación NO va en los headers.
En cada .c tenés que incluir el .h correspondiente.

Triper0

Cita de: Triper0 en 13 Agosto 2011, 00:05 AM
Lo fundamental que tenes que saber es lo siguiente:

Los .h (headers) contienen las CABECERAS de las funciones y también las estructuras (struct, union, etc).
En los .c respectivos a esos headers, tenes que poner la implementación de las cabeceras, y no te olvides, de incluir los headers, porque por ej, si vos en un header definís una estructura, y después en el .c de ese header, la usás y no incluíste el .h, no va a funcionar.

Otro dato importante es una macro que se usa para evitar problemas de inclusión del mismo header en un archivo

#ifndef _HEADER
#define _HEADER

IMPLEMENTACIÓN del .C

#endif

Eso también es importante, más que nada cuando son programas extensos.

Bueno, está de más decir que los .h tenes que incluirlos en el main.

Ahora lo importante es la compilación. Vos tenes que compilar todos los .c, en este caso, supongamos que es A.h A.c, B.h, B.c, main.c

sería

gcc -o programa.exe main.c a.c b.c -Wall

Imaginate si tenes 800.h con sus respectivos c... ¿Medio largo no?

Bueno, entonces hacemos

gcc -o programa.exe *.c -Wall y te incluye todo por arte de magia

Ahora bien, acordate de también tener todos los archivos en la misma carpeta, porque si vos los incluís de la forma "asd.h" quiere decír que está en la misma carpeta

Creo que con esto se te va a solucionar el problema, aunque realmente no sé qué es lo que queres preguntar.

En el caso que esto no te sirva de nada, lo mejor sería que pongas el código y ahí nos vamos a dar cuenta más fácil...

Saludos!

Relee todo lo que te puse...
Y por convención el #ifndef #define va con _ al principio, ej:

#ifndef _HEADER
#define _HEADER

#endif

Salud...

mariyop

Ya sé que la implementación no va en los headers, pero los archivos me los dieron así. Hay más gente trabajando con ellos.
Por cierto, ya tengo la solución. Me daba la lata el guión bajo de
#ifndef MATH_MODIF_H_. Cuando he cambiado el nombre del archivo y he puesto
#ifndef MATHMODIF_H_ se ha arreglado. Sin embargo, lo del guión después de los #defines,etc que dice Triper0 no da error, pero de todos modos, lo corregiré. Gracias