C/C++、FORTRAN、下划线和 GNU Autotools

发布于 2024-12-23 02:03:25 字数 3712 浏览 1 评论 0原文

我有关于混合语言编程(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 函数最常包含 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

Using Dev。 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-第二个下划线?),或者 3)两者的某种组合?

我已经接近了吗?如果是,我该如何构建应用程序?

I have a question about mixed-language programming (C/C++ and FORTRAN)
using gcc and gfortran. I've searched plenty of "mixing fortran with
language X" and haven't been able to resolve this.

I'm not sure if this is a linking problem or a compiler problem, or both.

I've created three files and I'm using GNU Autotools to build the
crude application, but should be able to build the app from command
line independently.

The C File (main.c) will be the driving app, that calls several
FORTRAN functions:

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

}

The fortran function which will most often contain FORTRAN 77 (but
can also include FORTRAN90/95 code too), looks like:

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

Using Dev. Studio 6/Compaq Digital Fortran 6.0, this works fine. In
fact, I don't have to use the #define ifdef __cplusplus/#endif and can
simply create a C file that looks like:

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

and compile it with the FORTRAN listing above, the application links,
runs, and generates the correct results.

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

C:\fooonly>

When I try top repeat this process using GNU Autotools on MinGW or
OSX, I continue to get the following errors:

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 $ 

where the Makefile (generated by GNU Autotools), basically contains
the following commands:

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 $ 

My configure.in script contains nothing more than:

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)

which is essentially,

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

right?

I'm trying to build this on multiple platforms (Linux, Win32/64, OSX,
etc.) and wish to use GNU Autotools, and I know this is done with
other open-source projects, but the configure.in scripts for those
projects are way beyond my GNU Autotools newbie chops and I get a
little overwhelmed trying to decode them.

I'm guessing this has something to do with:

1) The definitions I've used in the configure.in script,
2) I'm not including some magical set of switches
(i.e. -fno-second-underscore?), or
3) Some combination of the two?

Am I close and if so, how do I get the app to build?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尸血腥色 2024-12-30 02:03:25

只要您拥有比过去几年更新的编译器,我建议使用 ISO C 绑定将 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

As long as you have a compiler newer then the past several years, I recommend using the ISO C Binding to mix Fortran with other languages. Then you can skip the name mangling with underscores and similar compiler/platform dependent issues. If you have legacy FORTRAN 77 code that you don't want to alter, you could write a small Fortran 2003 glue routine between the C and the FORTRAN 77. Older instructions describe the previous method which required more understanding of the internal interfaces and was more compiler/platform dependent. For the new method, look at the gfortran manual chapter "Mixed Language Programming" and previous questions/answers here.

With Fortran code it is easier to link with gfortran because that brings in the Fortran runtime libraries. I think that the same applies to C++, so if you have both you will have to explicitly include the runtime library of one or the other.

P.S. Here is an example using the Fortran ISO C Binding:

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

Compile/link with:

gcc -c main.c
gfortran main.o ngcd.f90
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文