简体   繁体   中英

Calling a C++ function from a C++ function called by a FORTRAN code

I am trying to send some data from a FORTRAN (f90) code to a C++ function. The simplified working code would look like: 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

and the 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

and my 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)

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

Next, I would like to call another cpp function to do some operations on the data that now I have in func.cpp. An oversimplified version would look like: 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 */

And the updated 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)

I also update the func.cpp as:

  #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

I haven't been able to compile the code. I am not sure, but I guess something is wrong with the makefile since each time that I change the order of the object files, I get different errors such as:

  /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

or

  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'

I would appreciate any help on this issue.

Just as the comments suggest, add the correct run-time library for C++ when linking with a Fortran compiler

FORTRAN_FLAG = -lstdc++ -o

With GCC you can even just do

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

You could also link with the C++ compiler and add the Fortran libraries to the link command.

Note there is no iso_c_binding anywhere in your code, even though you use the tag and you reference it in the title. It is a modern way to interface C and Fortran. If you want to know more about the modern approaches read the tag wiki page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM