Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU Fortran and C interoperability

I have a large, mixed C/Fortran, code base, currently compiled using the Intel tools on Windows. I've been asked to port it to the GNU tools, on Linux. More or less at random, I've selected version 4.8.

Where a C function is called from Fortran, the interoperability often looks like this:

// C code:
void PRINTSTR(char *str, size_t len) {
    for(int ii = 0; ii < len; ii++) {
        putchar(str[ii]);
    }
    putchar('\n');
}

!Fortran code:
program test
implicit none
call printstr("Hello, world.")
end

The Intel Fortran compiler always generates upper-case symbols, so this works fine. But the GNU Fortran compiler always generates lower-case symbols and so there is a linker error.

The GNU Fortran compiler used to have an option called -fcase-upper which made it generate upper-case symbols, but it seems this was too configurable for everyone's good and it has been removed (I'm not exactly sure when).

It's possible to use the ISO_C_BINDING facility to force the compiler to generate a case-sensitive name:

program test
interface
subroutine printstr(str) bind(C, name='PRINTSTR')
character :: str(*)
end subroutine
end interface

call printstr("Hello, world.")
end

This resolves the linker error but it changes how string parameters are handled; the length parameter is no longer provided. So to use this method, I'd not only have to add interface definitions for every function that currently works this way, but I'd also have to change how strings are handled in every call to such a function, making sure that all strings are null-terminated.

I could go through and make all such functions lower-case, but of course the Intel compiler still generates upper-case symbols, so that would break the existing build.

Since there are ~2,000 such functions, that seems an infeasible amount of work. So, my question is this: How can I resolve the link errors without changing the function call semantics and without breaking the existing build using the Intel compilers?

like image 333
Tom Avatar asked Nov 01 '22 15:11

Tom


1 Answers

To solve the linker error you can do it other way around. Use Intel compiler option names to convert external names to lowercase to match the default GNU Fortran option. And convert name in c to lowercase too:

void printstr(char *str, size_t len) {...}

Personally I would recommend using -funderscoring and Intel's /assume:underscore to distinguish functions that are intended for interoperability.

// C code:
void printstr_(char *str, size_t len) {...}

!Fortran code:
program test
implicit none
call printstr("Hello, world.")
end
like image 194
Peter Avatar answered Nov 04 '22 08:11

Peter