从FORTRAN代码调用的C ++函数调用C ++函数

时间:2014-08-04 21:02:54

标签: c++ makefile fortran fortran90

我正在尝试将FORTRAN(f90)代码中的一些数据发送到C ++函数。简化的工作代码如下所示: 的 main.f90时

  program test
  !
     integer:: ii, jj, kk
     common/ijk/ ii, jj, kk
     character*32 cc
     ii = 2
     jj = 3
     kk = 4
     cc = 'Example of a character string'
  !
     call doubleIJK(cc)
  !
     write(*,*) ii, jj, kk
  !
  end program test

func.cpp

  #ifdef __cplusplus
     extern"C" {
  #endif

  #include <stdio.h>

  extern struct
  {
     int ii, jj, kk;
  } ijk_;

  void *__gxx_personality_v0;

  int doubleijk_(char *cc, int ll)
  {
     cc[ll--] = '\0';  // NULL terminate the string
     printf("From doubleIJK: %s\n",cc);
     ijk_.ii *=2;
     ijk_.jj *=2;
     ijk_.kk *=2;
     return(1);
  }

  #ifdef __cplusplus
     }
  #endif

和我的 Makefile

  # Compilers
  FORTRAN_COMPILER = ifort
  CPP_COMPILER = g++

  # Flags
  CPP_FLAG = -c #-lstdc++
  FORTRAN_FLAG = -o

  # Rules:
  test.exe: main.o func.o
      $(FORTRAN_COMPILER) $(FORTRAN_FLAG) test.exe main.o func.o

  # Objects
  func.o: func.cpp
      ($(CPP_COMPILER) $(CPP_FLAG) func.cpp)

  main.o: main.f90
      ($(FORTRAN_COMPILER) $(CPP_FLAG) main.f90)

========================================

接下来,我想调用另一个cpp函数对func.cpp中现有的数据进行一些操作。过度简化的版本看起来像: 的 addition.cpp

  #include <iostream>
  #include "addition.h"

  using namespace std;

  int addition (int a, int b)
  {
    int r;
    r = a + b;
    cout << r << endl;
    return r;
  }

addition.h

  #ifndef ADDITION_H
  #define   ADDITION_H
  int addition (int a, int b);
  #endif /* ADDITION_H */

更新的 Makefile

# Compilers
FORTRAN_COMPILER = ifort
CPP_COMPILER = g++

# Flags
CPP_FLAG = -c #-lstdc++
FORTRAN_FLAG = -o

# Rules:
test.exe: main.o func.o addition.o
   $(FORTRAN_COMPILER) $(FORTRAN_FLAG) test.exe main.o func.o addition.o

# Objects
func.o: func.cpp
    ($(CPP_COMPILER) $(CPP_FLAG) func.cpp)

addition.o: addition.cpp
   ($(CPP_COMPILER) $(CPP_FLAG) addition.cpp)

main.o: main.f90
   ($(FORTRAN_COMPILER) $(CPP_FLAG) main.f90)

我还将 func.cpp 更新为:

  #ifdef __cplusplus
     extern"C" {
  #endif

  #include <stdio.h>
  #include "addition.h"

  extern struct
  {
     int ii, jj, kk;
  } ijk_;

  void *__gxx_personality_v0;

  int doubleijk_(char *cc, int ll)
  {
     cc[ll--] = '\0';  // NULL terminate the string
     printf("From doubleIJK: %s\n",cc);
     ijk_.ii *=2;
     ijk_.jj *=2;
     ijk_.kk *=2;

     int z;
     z = addition (5,3);

     return(1);
  }

  #ifdef __cplusplus
     }
  #endif

我还没能编译代码。我不确定,但我想makefile有问题,因为每次我更改目标文件的顺序时,我会得到不同的错误,例如:

  /tmp/cc4AuTkF.o(.text+0x50): In function `doubleijk_':
  : undefined reference to `ijk_'
  /tmp/cc4AuTkF.o(.text+0x58): more undefined references to `ijk_' follow
  collect2: ld returned 1 exit status
  make: *** [func.o] Error 1

  func.o(.text+0x67): In function `doubleijk_':
  : undefined reference to `addition'
  addition.o(.text+0x23): In function `__static_initialization_and_destruction_0(int, int)':
  : undefined reference to `std::ios_base::Init::Init()'
  addition.o(.text+0x28): In function `__static_initialization_and_destruction_0(int, int)':
  : undefined reference to `std::ios_base::Init::~Init()'
  addition.o(.text+0x6f): In function `addition(int, int)':
  : undefined reference to `std::cout'

我很感激在这个问题上的任何帮助。

1 个答案:

答案 0 :(得分:2)

正如评论所示,在与Fortran编译器链接时为C ++添加正确的运行时库

FORTRAN_FLAG = -lstdc++ -o

使用GCC你甚至可以做到

gfortran *.cpp *.f90 -lstdc++ -o test.exe

您还可以链接到C ++编译器并将Fortran库添加到链接命令。

请注意,代码中没有iso_c_binding,即使您使用标记并在标题中引用它。它是接口C和Fortran的现代方式。如果您想了解更多关于现代方法的信息,请阅读标签维基页面。