I am writing a C++/Fortran mixed programming where a Fortran subroutine is called from within the C++ main program.
In the file c-call-f.cpp
:
#include <iostream>
extern "C"
{
void for_sub_(int *, double *, double *, int *);
}
int main()
{
int i = 1, ny = 3;
double x = 3.14159;
double y[] = {1.1, 2.2, 3.3};
for_sub_(&i, &x, y, &ny);
return 0;
}
While in the f_sub.f90
file:
subroutine FOR_SUB(i,x,y,ny)
use, intrinsic :: iso_c_binding
implicit none
integer(c_long) :: i, ny
real(c_double) :: x
real(c_double) :: y(ny)
print *, "y = ", y(1:ny)
end subroutine FOR_SUB
The code above is inspired by a tutorial on C/Fortran programming found here: Fortran calling C functions
I want to replicate the code for C++/Fortran. I compiled them with
gfortran -c f_sub.f90
g++ -c c-call-f.cpp
g++ f_sub.o c-call-f.o
But I got error saying
Undefined symbols for architecture x86_64:
"__gfortran_st_write", referenced from:
_for_sub_ in f_sub.o
"__gfortran_st_write_done", referenced from:
_for_sub_ in f_sub.o
"__gfortran_transfer_array_write", referenced from:
_for_sub_ in f_sub.o
"__gfortran_transfer_character_write", referenced from:
_for_sub_ in f_sub.o
"__gfortran_transfer_integer_write", referenced from:
_for_sub_ in f_sub.o
"__gfortran_transfer_real_write", referenced from:
_for_sub_ in f_sub.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)`
What is causing the error? I also tried adding flag -lf
, -lfortran
or -lg2c
in the last compilation step, but another error arises:
ld: library not found for [flag]
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Where [flag]
is any of the three mentioned above.
BTW, why are resources on C/Fortran interoperability that I found online appears to be so inconsistent, in one place I read that you need to give a bind(C)
after the procedure name in its declaration while in another place such as the link given above, you don't need to. Other thing, I read someone said that you don't need to add trailing underscore following a subroutine name in the calling unit but in the other places you need to. It is confusing, which of them are wrong?