C / C ++, FORTRAN, guiones bajos y autotools GNU

Tengo una pregunta sobre la progtwigción en lenguaje mixto (C / C ++ y FORTRAN) usando gcc y gfortran. He buscado un montón de “mezclando fortran con el lenguaje X” y no he podido resolver esto.

No estoy seguro de si se trata de un problema de vinculación o de comstackción, o de ambos.

He creado tres archivos y estoy usando GNU Autotools para construir la aplicación en bruto, pero debería poder construir la aplicación desde la línea de comandos de forma independiente.

El archivo C (main.c) será la aplicación de conducción, que llama a varias funciones de FORTRAN:

/* this is a simple program */ #include  /* add the extern function definition */ #include "fooonly.h" // this is not working for the mixed language programming stuff yet... /* this is the main program section */ int main( int argc, char *argv[] ) { int a = 36; int b = 24; int c = 0; printf( "hi mom\n" ); /* now call a FORTRAN function from C */ c = NGCD( &a, &b ); printf( "NGCD(%d,%d)=%d\n", a, b, c ); return 0; 

}

La función fortran que con más frecuencia contendrá FORTRAN 77 (pero también puede incluir el código FORTRAN90 / 95 también), se ve así:

 c$$$ The following introductory example in FORTRAN 77 finds the c$$$ $ greatest common divisor for two numbers A and B using a c$$$ $ verbatim implementation of Euclid's algorithm. FUNCTION NGCD(NA, NB) IA = NA IB = NB 1 IF (IB.NE.0) THEN ITEMP = IA IA = IB IB = MOD(ITEMP, IB) GOTO 1 END IF NGCD = IA RETURN END 

Usando Dev. Studio 6 / Compaq Digital Fortran 6.0, esto funciona bien. De hecho, no tengo que usar el #define ifdef __cplusplus / # endif y simplemente puedo crear un archivo C que se parece a:

 /* this is a simple program */ #include  /* add the extern function definition */ extern "C" int __stdcall NGCD( int *a, int *b ); /* this is the main program section */ int main( int argc, char *argv[] ) { int a = 36; int b = 24; int c = 0; printf( "hi mom\n" ); /* now call a FORTRAN function from C */ c = NGCD( &a, &b ); printf( "NGCD(%d,%d)=%d\n", a, b, c ); return 0; } 

y compílalo con el listado FORTRAN anterior, la aplicación enlaza, ejecuta y genera los resultados correctos.

 C:\fooonly>fooonly.exe hi mom NGCD(36,24)=12 C:\fooonly> 

Cuando bash repetir este proceso utilizando GNU Autotools en MinGW u OSX, continúo obteniendo los siguientes errores:

 macbook:makecheck $ make gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"fooonly\" -DVERSION=\"1.0.2\" -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c mv -f .deps/main.Tpo .deps/main.Po gfortran -g -O2 -o fooonly main.o ngcd.o Undefined symbols for architecture x86_64: "_NGCD", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status make: *** [fooonly] Error 1 macbook:makecheck $ 

donde el Makefile (generado por GNU Autotools), básicamente contiene los siguientes comandos:

 macbook:makecheck $ gcc -c main.c macbook:makecheck $ gfortran -c ngcd.f macbook:makecheck $ gcc -o fooonly main.c ngcd.o Undefined symbols for architecture x86_64: "_NGCD", referenced from: _main in cc9uPBWl.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status macbook:makecheck $ 

Mi script configure.in no contiene nada más que:

 AC_INIT(main.c) AM_INIT_AUTOMAKE(fooonly, 1.0.2) ## C/C++ compiler section AC_PROG_CC ## fortran section AC_PROG_F77 ## output section AC_OUTPUT(Makefile) 

que es esencialmente,

 macbook:makecheck $ gcc -c main.c macbook:makecheck $ gfortran -c ngcd.f macbook:makecheck $ gcc -o fooonly main.c ngcd.o 

¿Correcto?

Estoy tratando de construir esto en múltiples plataformas (Linux, Win32 / 64, OSX, etc.) y deseo usar GNU Autotools, y sé que esto se hace con otros proyectos de código abierto, pero los scripts de configure.in para aquellos Los proyectos van mucho más allá de mis habilidades para principiantes de GNU Autotools y me siento un poco abrumado al intentar decodificarlos.

Supongo que esto tiene algo que ver con:

1) Las definiciones que he usado en la secuencia de comandos configure.in, 2) No estoy incluyendo algún conjunto mágico de interruptores (es decir, ¿-fno-segundo-guión bajo?), O 3) ¿Alguna combinación de los dos?

¿Estoy cerca y, en caso afirmativo, cómo puedo crear la aplicación?

Siempre que tenga un comstackdor más nuevo que los últimos años, recomiendo usar el enlace ISO C para mezclar Fortran con otros idiomas. Luego, puede omitir el nombre de los nombres con guiones bajos y problemas similares dependientes del comstackdor / plataforma. Si tiene un código heredado de FORTRAN 77 que no desea modificar, puede escribir una pequeña rutina de cola Fortran 2003 entre la C y el FORTRAN 77. Las instrucciones anteriores describen el método anterior que requería una mayor comprensión de las interfaces internas y era más comstackdor / plataforma dependiente. Para conocer el nuevo método, consulte el capítulo del manual de gfortran “Progtwigción en varios idiomas” y las preguntas / respuestas anteriores aquí.

Con el código de Fortran es más fácil vincularlo con gfortran porque eso trae las bibliotecas de tiempo de ejecución de Fortran. Creo que lo mismo se aplica a C ++, por lo que si tiene ambos tendrá que incluir explícitamente la biblioteca de tiempo de ejecución de uno u otro.

PS Aquí hay un ejemplo utilizando el enlace ISO C de Fortran:

 function NGCD (na, nb) bind (C, name="NGCD") use iso_c_binding implicit none integer (c_int) :: ngcd integer (c_int), intent (in) :: na, nb integer (c_int) :: ia, ib, itemp ia = na ib = nb do while (ib /= 0) itemp = ia ia = ib ib = mod(itemp, ib) end do ngcd = ia return end function NGCD 

Comstackr / enlazar con:

 gcc -c main.c gfortran main.o ngcd.f90 

Nunca obtuve una respuesta suficiente, por lo que armé una solución temporal (ignora el caso en el código FORTRAN) y la publiqué en mi blog de forufus . Tendré que trabajar con los conmutadores del comstackdor en el futuro.

Intereting Posts