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.