2

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?

CKE
  • 1,533
  • 19
  • 18
  • 29
nougako
  • 234
  • 1
  • 8
  • It could be compiler specific. You should link both C++ and Fortran standard libraries, so link with `g++ f_sub.o c-call-f.o -lfortran` – Basile Starynkevitch Sep 01 '18 at 09:25
  • @BasileStarynkevitch, as I said in my question, I have tried using that library but I got `ld: library not found for -lfortran` error. – nougako Sep 01 '18 at 09:35
  • Then you need to find that library, and that makes a very different question. On Debian you need the `libgfortran-8-dev` package (with `gfortran-8`) and pass `-L /usr/lib/gcc/x86_64-linux-gnu/8/` and `-lgfortran` to your linking command – Basile Starynkevitch Sep 01 '18 at 09:35
  • Ok I will try to find solution on that issue first, I will see if it resolves the error. – nougako Sep 01 '18 at 09:37
  • 1
    So compile your C++ code with `g++ -Wall -g -c`, your Fortran code with `gfortran -Wall -g`, and link with `g++ -L /usr/lib/gcc/x86_64-linux-gnu/8/ f_sub.o c-call-f.o -lgfortran`. Replace the `8` by the major version of `g++` & `gfortran`. So try first `g++ -v` then `gfortran -v` to find their version – Basile Starynkevitch Sep 01 '18 at 09:42
  • 4
    Do people in the C++ tag really deal so quickly (dupehammer) with any `undefined reference` question? I am surprised none of the targets here are about gfortran at all. I saw something similar in the Java tag when they instaclose anything involving null pointer as a duplicate of "what is a null pointer exception". We don't really do that in Fortran tag. This is clearly a duplicate of some other question, that mentions `-lgfortran`, but just any "undefined reference"? – Vladimir F Героям слава Sep 01 '18 at 10:26
  • Thanks for the hint @VladimirF, using -lgfortran for the linking step the problem "seems" to be resolved. It does not produce the above error, but now the dummy variable `ny` becomes 4294967299 which causes a segfault due to index out of bound in the `print *, "y = ", y(1:ny)`. Btw I am new in c++ but even so looking at the suggested duplicate questions, I do think the subject of those questions are still too general to be able to be helpful for my issue. – nougako Sep 01 '18 at 11:41
  • That is a new problem for a new question and will require a good [mcve]. – Vladimir F Героям слава Sep 01 '18 at 11:55
  • Never mind, it was a silly mistake of not using long int when declaring the integers in the c++ side. Problem solved. – nougako Sep 01 '18 at 12:09
  • 3
    The tutorial referred to, and any other suggestion to use name-mangling (such as adding underscores when calling C from Fortran, etc), has been out of date since the widespread implementation of Fortran's *interoperability with C* features, introduced in the 2003 (I think) standard. That defined a common and portable approach to interoperability, with features such as `bind` for specifying the name a Fortran routine should be called with by a C program. OP's last paragraph points to a common confusion of the old, non-standard approach to interoperability, and the new standard approach. – High Performance Mark Sep 01 '18 at 12:20
  • 3
    ... and the 'right' answer to the question is not *get your external references right* (though that might be important too) but *Use the modern Fortran/C interoperability features implemented by all current and widely used Fortran compilers and a companion C compiler*. – High Performance Mark Sep 01 '18 at 12:23
  • @nougako Did you need the `-lgfortran` flag in the end? This is the supposed problem. Also, if we mark as duplicate I agree with Vladimir that the generic answers provided are pretty useless for a Fortran programmer. – Pierre de Buyl Sep 04 '18 at 09:02
  • @PierredeBuyl, yes the problem was solved as I indicated in my two previous comment. After using `-lgfortran` instead of `-lfortran` as I did in my first attempt, the program runs except that there was another type error but this was also solved. – nougako Sep 05 '18 at 02:55
  • @VladimirF do you have an obvious other answer as the duplicate? Could we point to that instead of the current ones? – Pierre de Buyl Sep 05 '18 at 07:47
  • 2
    @PierredeBuyl I quickly searched some and put them there, but you might be able to find better ones. – Vladimir F Героям слава Sep 05 '18 at 09:21
  • The first (new) link is really spot on for my problem. – nougako Sep 05 '18 at 11:51

0 Answers0