Visible to Intel only — GUID: GUID-3B67E78D-15AC-42E8-9593-E6F6E97CD50B
Visible to Intel only — GUID: GUID-3B67E78D-15AC-42E8-9593-E6F6E97CD50B
Global Data
A module variable or a common block can interoperate with a C global variable if the Fortran entity uses the BIND attribute and the members of that entity are also interoperable. Consider the entities c_extern, c2, com and single in the following module's interoperability example:
module LINK_TO_C_VARS
use, intrinsic :: ISO_C_BINDING
integer(C_INT), BIND(C) :: c_extern
integer(C_LONG) :: c2
BIND(C, name='myVariable') :: c2
common /com/ r,s
real(C_FLOAT) :: r,s,t
BIND(C) :: /com/, /single/
common /single/ t
end module LINK_TO_C_VARS
This example can interoperate with the following C external variables:
int c_extern; long myVariable; struct {float r, s;} com; float single;
Accessing global parameters example:
MODULE Examp
integer, BIND(C)::idata(20)
real::rdata(10)
END MODULE
In Fortran, a variable can access a global parameter by using the standard BIND C attribute.
In the above, two external variables are created (the latter with proper case and decoration): idata and foo_mp_rdata.
Use the BIND attribute to resolve name discrepancies with C, seen in the global variable statement example:
int idata[20]; // declared as global (outside of any function)
Fortran can declare the variable global (COMMON) and other languages can reference it as external, for example:
! Fortran declaring PI global
real pi_r
COMMON /pi/ pi_r ! Common Block and variable names
BIND(C)::/pi/
Use of BIND(C) above means that the name will be appropriately decorated for the target and made lowercase. In C, the variable is referenced as an external with the statement:
//C code with external reference to pi extern float pi;
The global name C references is the name of the Fortran common block (pi), not the name of a variable within a common block (pi_r). Therefore, you cannot use blank common (unnamed) to make data accessible between C and Fortran.
COMMON
To reference C structures from Fortran common blocks and vice versa, you must take into account how common blocks and structures differ in their methods of storing member variables in memory. Fortran places common block variables into memory in order as close together as possible, with the following rules:
A single BYTE, INTEGER(1), LOGICAL(1), or CHARACTER variable in common block list begins immediately following the previous variable or array in memory.
All other types of single variables begin at the next even address immediately following the previous variable or array in memory.
All arrays of variables begin on the next even address immediately following the previous variable or array in memory, except for CHARACTER arrays which always follow immediately after the previous variable or array.
All common blocks begin on a four-byte aligned address.
Because of these rules, you must consider the alignment of C structure elements with Fortran common block elements. Specifically, you should ensure interoperability either by making all variables exactly equivalent types and kinds in both languages (using only 4-byte and 8-byte data types in both languages simplifies this) or by using the C pack pragmas in the C code around the C structure. This makes C data packing compatible with Fortran data packing.
As an example, suppose your Fortran code has a common block named Really, as shown in the Fortran example::
USE, INTRINSIC::ISO_C_BINDING
REAL (C_float)::x,y,z(6)
REAL (C_double)::ydbl
COMMON, BIND(C) / Really /x, y, z(6), ydbl
You can access this data structure from your C code with the following external data structures, as shown in the C example:
#pragma pack(2) extern struct { float x, y, z[6]; double ydbl; } Really; #pragma pack()
To restore the original packing, you must add #pragma pack() at the end of the C structure.
You can also access C structures from Fortran by creating common blocks that correspond to those structures. This is the reverse case from that shown above. However, the implementation is the same; after common blocks and structures have been defined and given a common address (name), and, assuming the alignment in memory has been accounted for, both languages share the same memory locations for the variables.
Once you have accounted for alignment and padding, you can give C access to an entire common block or set of common blocks. Alternatively, you can pass individual members of a Fortran common block in an argument list, just as you can any other data item.