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博客上。 我将来必须编制编译器开关。