Module Variables and ISO_C_BINDING

      ! Ubuntu 16.04 + PGI 18.10
      ! m.f

      ! ifort -c m.f
      ! gfortran -c m.f
      ! pgfortran -c m.f

      ! nm -n m.o

      module f
      use iso_c_binding
      implicit none
      integer x
      integer, bind(c,name='YY') :: y
      save
      end

Hey guys, with the source code and commands showed above, I got

0000000000000004 C _YY
0000000000000004 C _f_mp_x_

0000000000000000 S ___f_MOD_x
0000000000000004 C _YY

from ifort and gfortran compilers. I was expecting to see similar outputs from PGI Fortran compiler (and relying on the similar features) but all I had was

0000000000000000 T f_
0000000000000004 C _f_0_

My intent was to access the global variables defined in Fortran modules from C, but it seemed impossible now.

/*   pgcc main.c m.o   */
extern int YY;
int main() {
  YY = 42;
  return 0;
}

gave “undefined reference to `YY’” error.

Any suggestions?

Thanks,
SW

Hi SW,

Looks like a compiler issue to me. Hence I’ve added a problem report (TPR#27090) and sent it to our compiler engineers for further investigation.

The work around would be to add a stub routine in the module that references the variable. We correctly generate the symbol in this case.

% cat test.F90
module f
use iso_c_binding
implicit none
integer x
integer(C_INT), bind(C,name='YY'), dimension(1) :: Y
#ifdef USE_SUB
contains
subroutine fortranstub() bind(C)
print *, "Y=",Y
end subroutine
#endif
end module f

% cat main.c
/* pgcc main.c m.o */
extern int YY;
int main() {
YY = 42;
printf("%d\n",YY);
return 0;
}

% pgf90 -c test.F90
% nm test.o
0000000000000000 A ..Dm_f
0000000000000000 T f_
0000000000000004 C _f_0_
U iso_c_binding_
U _iso_c_binding_10_
% pgcc main.c test.o -pgf90libs
main.c:
main.o: In function `main':
/local/home/colgrove/fs21375/./main.c:4: undefined reference to `YY'
/local/home/colgrove/fs21375/./main.c:5: undefined reference to `YY'
% pgf90 -c test.F90 -DUSE_SUB
% nm test.o
0000000000000038 d .C2_283
0000000000000040 d .C2_285
0000000000000044 d .C2_299
0000000000000000 d .C2_315
0000000000000030 d .C2_317
0000000000000034 d .C2_318
0000000000000010 d .C2_321
000000000000003c d .C2_325
0000000000000000 A ..Dm_f
0000000000000000 T f_
0000000000000004 C _f_0_
U f90_compiled
0000000000000010 T fortranstub
000000000000008e t __fortranstubEND
U iso_c_binding_
U _iso_c_binding_10_
U pgf90io_ldwa
U pgf90io_ldw_aa
U pgf90io_ldw_end
U pgf90io_print_init
U pgf90io_sc_ch_ldw
U pgf90io_src_info03a
0000000000000004 C YY
% pgcc main.c test.o -pgf90libs
main.c:
% a.out
42

Thanks for the report!
Mat

Thank you, Mat.

I noticed that the symbols and number of symbols without iso_c_binding cannot be directly identified in .o file. I am not familiar with Fortran standards but I would assume it is implementation-dependent. Is it the expected behavior here for PGI compiler?

Thanks,
SW

      module f
      use iso_c_binding
      implicit none
      integer x,a,b,c
      integer, bind(c,name='YY') :: y
      integer, bind(c,name='ZZ') :: z

      contains
      subroutine stub() bind(c)
      x = 0
      a = 0
      b = 0
      c = 0
      y = 0
      z = 0
      end
      end
      
// pgf90
0000000000000000 T f_
0000000000000000 V YY
0000000000000004 V ZZ
0000000000000010 C _f_0_
0000000000000010 T stub

// gfortran
0000000000000000 B __f_MOD_a
0000000000000000 T stub
0000000000000004 B __f_MOD_b
0000000000000004 C YY
0000000000000004 C ZZ
0000000000000008 B __f_MOD_c
000000000000000c B __f_MOD_x

I would assume it is implementation-dependent.

Correct. Module layout is implementation dependent and one reason why most F90 implementations are not inter-operable.

PGI will layout the data members of a module as an offset from the base data address. In your case “f_0” is the start of the module data.

While I’m not a compiler engineer myself, I believe why we lay it out this way is mostly due to legacy. PGI was founded in 1989 as a spin-off from Floating Point Systems (FPS) where our founders took an internal FPS developed HPF (High Performance Fortran) compiler and productized it for the HPC market. When we later developed a F90 compiler in the early-90s, we used the same format as we did common blocks given modules are really just a better form of a common block.

-Mat

Thanks for your explanation.