2011-12-26 59 views
3

我对使用gcc和gfortran的混合语言编程(C/C++和FORTRAN) 有疑问。我搜索了很多“混合fortran与 语言X”,并没有能够解决这个问题。C/C++,FORTRAN,下划线和GNU Autotools

我不确定这是链接问题还是编译器问题,或者两者兼而有之。

我创建了三个文件,我使用GNU Autotools来构建 原始应用程序,但应该能够独立地从命令 行建立应用程序。

C文件(main.c中)将所述驱动程序,即调用几个 FORTRAN功能:

/* this is a simple program */ 

#include <stdio.h> 

/* 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 

使用开发。工作室6 /康柏数字Fortran 6.0,这工作正常。在 其实,我没有使用的#define IFDEF __cplusplus /#ENDIF和可 只需创建一个C文件看起来像:

/* this is a simple program */ 

#include <stdio.h> 

/* 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自动工具产生的),基本上包含 以下命令:

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-第二下划线?)或 3)两者的一些组合?

我关闭了吗?如果是这样,我该如何让应用程序构建?

+0

“macbook:makecheck $ gcc -o fooonly main.c ngcd.o”你不应该更好地传递'main.o'而不是'main.c'吗? – 2011-12-26 18:35:30

+0

是的,确实如此。这是一个错字。 – user1116524 2011-12-26 20:12:21

回答

4

只要你有一个新的编译器,那么在过去的几年中,我推荐使用ISO C绑定来将Fortran与其他语言混合使用。然后,您可以跳过名称与下划线和类似的编译器/平台相关的问题。如果你有不想改变的遗留FORTRAN 77代码,你可以在C和FORTRAN 77之间编写一个小型的Fortran 2003胶水例程。以前的方法描述了以前需要更多理解内部接口的方法,编译器/平台依赖。对于新方法,请查看gfortran手册章节“混合语言编程”和此处的以前的问题/答案。

使用Fortran代码更容易与gfortran链接,因为这会引入Fortran运行时库。我认为这同样适用于C++,所以如果你有两个你将不得不明确包含一个或另一个的运行时库。

P.S.下面是使用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 
+0

一个很好的解决方案,在未来,我想我会建议合作者。不幸的是,我正在使用需要F77的遗留代码。 – user1116524 2011-12-28 21:30:26

+0

有时候我不了解遗留程序要保持F77的要求。我自己维护一个只有f95的程序,但f77太简单了。来自较新的Fortran标准的特性不会在旧程序的固定格式源代码中使用问题。很难找到只知道历史平台和大型机之外的F77的Fortran编译器。 – 2012-02-01 08:59:24

-1

我从来没有得到足够的答案,所以我拼凑出一个临时的解决方案(在FORTRAN忽略大小写代码)并将其发布到我的forufus博客上。我将来不得不编制编译器开关。