【问题标题】:C/C++, FORTRAN, underscores, and GNU AutotoolsC/C++、FORTRAN、下划线和 GNU Autotools
【发布时间】:2011-12-26 17:58:41
【问题描述】:

我有一个关于混合语言编程(C/C++ 和 FORTRAN)的问题 使用 gcc 和 gfortran。我已经搜索了很多“将 fortran 与 语言 X”,但无法解决此问题。

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

我创建了三个文件,我正在使用 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 77 的 fortran 函数(但 也可以包含 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

使用开发。 Studio 6/Compaq Digital 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 上的 GNU Autotools 或 OSX,我继续收到以下错误:

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) 两者的某种组合?

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

【问题讨论】:

  • "macbook:makecheck $ gcc -o fooonly main.c ngcd.o" 你不应该通过main.o而不是main.c吗?
  • 是的,确实如此。那是一个错字。

标签: c build-automation fortran gnu


【解决方案1】:

只要你有一个比过去几年更新的编译器,我建议使用 ISO C 绑定将 Fortran 与其他语言混合。然后,您可以跳过带有下划线和类似编译器/平台相关问题的名称修饰。如果您有不想更改的旧版 FORTRAN 77 代码,则可以在 C 和 FORTRAN 77 之间编写一个小的 Fortran 2003 粘合例程。较早的说明描述了以前的方法,该方法需要更多地了解内部接口,并且更多编译器/平台相关。对于新方法,请在此处查看 gfortran 手册章节“混合语言编程”和以前的问题/答案。

使用 Fortran 代码更容易与 gfortran 链接,因为它引入了 Fortran 运行时库。我认为这同样适用于 C++,因此,如果您同时拥有两者,则必须明确包含其中一个的运行时库。

附:这是使用 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

【讨论】:

  • 一个很好的解决方案,在未来,我想我会建议合作者。不幸的是,我正在使用需要 F77 的遗留代码。
  • 有时我不明白遗留程序保持 F77 的要求。我自己维护一个只有 f95 的程序,但 f77 实在是太过时了。来自较新的 Fortran 标准的功能在旧程序的固定格式源代码中使用时没有问题。在历史平台和大型机之外,很难找到只知道 F77 的 Fortran 编译器。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多