C / C ++,FORTRAN,下划线和GNU Autotools
我有一个关于使用gcc和gfortran的混合语言编程(C / C ++和FORTRAN)的问题。 我搜索了很多“用语言X混合fortran”并且无法解决这个问题。
我不确定这是链接问题还是编译器问题,或两者兼而有之。
我创建了三个文件,我使用GNU Autotools构建原始应用程序,但应该能够独立于命令行构建应用程序。
C文件(main.c)将是驱动应用程序,它调用几个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;
}
fortran函数最常包含FORTRAN 77(但也可以包含FORTRAN90 / 95代码),如下所示:
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
使用Dev。 Studio 6 / Compaq Digital Fortran 6.0,这很好用。 事实上,我不必使用#define ifdef __cplusplus /#endif,只需创建一个如下所示的C文件:
/* 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; }
并使用上面的FORTRAN列表进行编译,应用程序链接,运行并生成正确的结果。
C:\fooonly>fooonly.exe hi mom NGCD(36,24)=12 C:\fooonly>
当我尝试在MinGW或OSX上使用GNU Autotools重复此过程时,我继续收到以下错误:
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 $
其中Makefile(由GNU Autotools生成)基本上包含以下命令:
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 $
我的configure.in脚本只包含:
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)
基本上,
macbook:makecheck $ gcc -c main.c macbook:makecheck $ gfortran -c ngcd.f macbook:makecheck $ gcc -o fooonly main.c ngcd.o
对?
我正在尝试在多个平台(Linux,Win32 / 64,OSX等)上构建它,并希望使用GNU Autotools,我知道这是用其他开源项目完成的,但是那些configure.in脚本用于那些项目超出了我的GNU Autotools新手印章,我有点不知所措,试图解码它们。
我猜这与之有关:
1)我在configure.in脚本中使用的定义,2)我不包括一些神奇的开关集(即-fno-second-underscore?),或3)两者的某种组合?
我是否关闭,如果是这样,我如何让应用程序构建?
只要你有一个比过去几年更新的编译器,我建议使用ISO C Binding将Fortran与其他语言混合使用。 然后,您可以使用下划线和类似的编译器/平台相关问题跳过名称修改。 如果你有遗传的FORTRAN 77代码,你不想改变,你可以在C和FORTRAN 77之间编写一个小的Fortran 2003胶水例程。旧的指令描述了之前的方法,需要更多地了解内部接口,而且更多编译器/平台依赖。 对于新方法,请查看gfortran手册章节“混合语言编程”以及此前的问题/答案。
使用Fortran代码,它更容易与gfortran链接,因为它带来了Fortran运行时库。 我认为这同样适用于C ++,因此如果您同时拥有这两者,则必须明确包含其中一个的运行时库。
PS以下是使用Fortran ISO C绑定的示例:
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
编译/链接:
gcc -c main.c gfortran main.o ngcd.f90
我从来没有得到足够的答案,所以我拼凑了一个临时解决方案(忽略FORTRAN代码中的案例)并将其发布在我的forufus博客上。 我将来必须编制编译器开关。