1
votes

I experience problems calling a FORTRAN subroutine from C++ when the function is put into a library created with "ar rcs".

The FORTRAN routine (tt.f90) is:

Module A
contains
  Subroutine SubIF2(ii)
    Integer*8, Intent(In) :: ii
    write(*,*) "hello", ii
  End Subroutine SubIF2
End Module A

A c++ caller (testcpp.cpp) code is

#include <iostream>
using namespace std;
extern"C" {
  void __a_MOD_subif2(long long int *ii);
}
main(){
  long long int ii=5;
  __a_MOD_subif2(&ii);
  return 0;
}

A fortran caller (testf.f90) code is

Program test
  use A
  integer*8 :: i=1
  call SubIF2(i)
End Program test

the makefile is

p=/PathToMyWorkDirectory
all:
    gfortran -c tt.f90
    ar rcs libtt.a tt.o
    g++ -c testcpp.cpp
    gfortran -c testf.f90
    -gfortran -o testf90 testf.o tt.a
    -g++ tt.o testcpp.o -o testcpp -lgfortran
    -g++ -L$(p) -ltt testcpp.o -o testcpp -lgfortran
clean:
    -rm *.o *.mod
    -rm testf90
    -rm testcpp

While the "gfortran -o testf90 testf.o tt.a" and "g++ tt.o testcpp.o -o testcpp -lgfortran" yield a working executable, "g++ -L$(p) -ltt testcpp.o -o testcpp -lgfortran" crashes

testcpp.o: In function `main':
testcpp.cpp:(.text+0x18): undefined reference to `__a_MOD_subif2'
collect2: error: ld returned 1 exit status

Since linking works for the fortran executable, I cannot see anything wrong in the library creation.

Any idea what I missing here??

Thanks a lot.

Note: the final fortran function will all be binary, so adjusting the fortran code (e.g. iso_c_binding) is not an option.

1
Note: if you take the subroutine out of the Fortran module you will not need the compiler-specific .mod file ay more, and you will be able to call directly the subroutine without the __a_MOD_ prefix which is not portable. In my opinion, Fortran libraries should exhibit a module-free interface which makes things easier for users. - Anthony Scemama
There are some no trailing underscore switches that can be useful. Or you can add a trailing underscore in the c. Also if the f90 routine is public or uses a !DEC$ ATTRIBUTES ALIAS:subif2::subif2 then than can help. - Holmz
@Holmz bind(C,name="") is much better than the old DEC ALIAS. And more importantly, the question is about gfortran and gfortran doesn't care about DEC ATRTRIBUTES at all. No wonder, it is not DEC but GNU. - Vladimir F
@Vladimir glad you remembered the Bind. I am not sure if BIND is "much better"... Basically the needs that were addressed with DEC extensions we're needs that were acknowledged and got rolled in as "standards". So DEC became dogma in intent. - Holmz
@Holmz It is much better because it does the job in all conforming compilers including that one used in the question. Unlike the DEC directives which are implemented by a single compiler out of many. (There are different things in other compilers). Notably, the compiler in the question does not implement them. I don't thing it went to the standard just from DEC, similar capability exists elsewhere as well even in different programming languages. - Vladimir F

1 Answers

3
votes

you have to specify the library after the object file which uses a symbol defined in it, i.e.,

g++ -o testcpp testcpp.o -L. -ltt -lgfortran