C-interoperable global variables

In C, if you have a file containing just int something;, you’ve created a variable and allocated space in the object file for it (at least I think you have). If instead you write extern int something;, you don’t create space in the object file, the symbol has to be resolved at link time (some other object file needs to provide the variable).

Suppose you’re writing a mixed Fortran/C program and you have a global variable on the C side that you want to access from Fortran. The following works, I’ve tested it, but I don’t know why it works.

Fortran file:

module stuffmod
    use iso_c_binding
    implicit none
    integer(c_int), bind(c, name="something") :: something_f
end module
program test
    use stuffmod
    implicit none
    print *, something_f
end program

C file:

int something = 10;

How does the compiler know that something_f is, effectively, extern? What would I do instead if I wanted to create a global variable in the fortran object file, and access it from C using a declaration like extern int something?

Thanks

1 Like

Thanks, that does help. The key takeaway for me is that an explicit “extern”-like qualifier is not required in Fortran, and the linker just makes the right thing happen.

1 Like

It seems that the answer is missing (has been deleted?)… I had the very same question and would be interested in understanding how it works…

I tested a similar toy example, and it works the same, regardless the C variable is declared with or without the extern keyword, which confuses me (I’m not a C expert at all).

Probably the person has deleted his Discourse account.

Can anyone reproduce the answer?

It would be nice if Discord would indicate there is a deleted comment instead of leaving us to guess based on context.

I believe the issue (tentative definitions in C) is explained here compilation - Tentative definitions in C and linking - Stack Overflow

It is said that multiple definitions of a global variable is possible as long as it is initialized only once. But also that this is an extension.

I assume that bind(C) of a module variable in Fortran is a definition in the C terminology, i.e. that it is equivalent to not using the C extern keyword. So, the proper way should be to declare the variable on the C side with the extern keyword ?

The key here is to define what is meant by “proper”.

Nominally what one can strive toward is conformance. Say, conformance with

  1. “ISO/IEC 9899:2018, Programming languages—C”
  2. Fortran base language as per, say, “ISO/IEC 1539-1:2023”

and presuming a companion C processor conformant to 1 above and a Fortran processor conforming to 2. above are pertinent here.

Under such circumtances, section 18.9 Interoperation with C global variables in “ISO/IEC 1539-1:2023” is applicable and the operative term is “external linkage”.and the interoperation is with a “C variable whose name has external linkage.”

One can then grok through the standard document for “Programming languages—C” and objects that have “external linkage”, say section 6.9.2 External object definitions in N2310 2018 WG14 Working Draft document as a close-enough proxy for the official standard. Here, one will find more than one form of declarations indicating “external linkage”

For someone quickly passing by here and looking for “Cliff Notes”, I reckon the following simple example conforms:

  • program for the companion C processor:
#include <stdio.h>

extern int c_extern;  // external linkage

void C_func() {
  printf("In C_func: c_extern = %d\n", c_extern);
  return;  
}
  • Program for Fortran processor:
module m
   use, intrinsic :: iso_c_binding, only : c_int
   integer(c_int), bind(C, name="c_extern") :: foo = 42
   interface
      subroutine C_sub() bind(C, name="C_func")
      end subroutine 
   end interface
end module
   use m 
   call C_sub()
end
  • Processors in action:
C:\temp>gfortran -c c.c

C:\temp>gfortran -c -ffree-form p.f

C:\temp>gfortran c.o p.o -o p.exe

C:\temp>p.exe
In C_func: c_extern = 42

C:\temp>

Fortranners need to also grok through the Fortran standard for semantic rules, most of which place the onus on the programmer: an example of one such is, “A variable shall not be initially defined by more than one processor.”

1 Like

And a corollary with C main program this time.

  • program for the companion C processor:
#include <stdlib.h>

int c_extern = 42;  // external linkage

extern void F_sub();

int main( void ) {
  F_sub();
  return EXIT_SUCCESS;  
}
  • Program for Fortran processor:
module m
   use, intrinsic :: iso_c_binding, only : c_int
   integer(c_int), bind(C, name="c_extern") :: foo
contains
   subroutine F_sub() bind(C, name="F_sub")
      print *, "In F_sub: foo = ", foo
   end subroutine 
end module
  • Processors in action:
C:\temp>gfortran -c c.c

C:\temp>gfortran -c -ffree-form p.f

C:\temp>gfortran c.o p.o -o c.exe

C:\temp>c.exe
 In F_sub: foo =           42

C:\temp>
1 Like