Common external data structures include Fortran common blocks, and C structures and variables that have been declared global or external. All of these data specifications create external variables, which are variables available to routines outside the routine that defines them.
External variables are case-sensitive, so the cases must be matched between different languages, as discussed in the section on naming conventions. Common external data exchange is described in the following sections:
A variable can be shared between Fortran and C by declaring it as global (or COMMON) in one language and accessing it as an external variable in the other language. In Fortran programs, variables must be passed as arguments.
In Fortran, a variable can access a global parameter by using the EXTERN option for ATTRIBUTES. For example:
!DEC$ ATTRIBUTES C, EXTERN :: idata INTEGER idata (20)
EXTERN tells the compiler that the variable is actually defined and declared global in another source file. If Fortran declares a variable external with EXTERN, the language it shares the variable with must declare the variable global.
In C, a variable is declared global with the statement:
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:
! Fortran declaring PI global REAL PI COMMON /PI/ PI ! Common Block and variable have the same name
In C, the variable is referenced as an external with the statement:
//C code with external reference to PI0 extern float PI;
Note that the global name C references is the name of the Fortran common block, not the name of a variable within a common block. Thus, you cannot use blank common to make data accessible between C and Fortran. In the preceding example, the common block and the variable have the same name, which helps keep track of the variable between the two languages. Obviously, if a common block contains more than one variable they cannot all have the common block name. (See Using Fortran Common Blocks and C Structures.)
To reference C structures from Fortran common blocks and vice versa, you must take into account the way the 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, so that data is packed.
Note
If the -align commons or -align decommons compiler option is specified, C structures need to be padded accordingly.
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. Use of common blocks for mixed-language data exchange is discussed in the following sections:
You can access Fortran common blocks directly from C by defining an external C structure with the appropriate fields, and making sure that alignment and padding between Fortran and C are compatible. The C and ALIAS ATTRIBUTES options can be used with a common block to allow mixed-case names.
As an example, suppose your Fortran code has a common block named Really
,
as shown:
!DEC$ ATTRIBUTES ALIAS:'Really' :: Really REAL(4) x, y, z(6) REAL(8) ydbl COMMON / Really / x, y, z(6), ydbl
You can access this data structure from your C code with the following external data structure:
extern struct { float x, y, z[6]; double ydbl; } Really;
You can also access C structures from Fortran by creating common blocks that correspond to those structures. This is the reverse case from that just described. However, the implementation is the same because after common blocks and structures have been defined and given a common address (name), and assuming the alignment in memory has been dealt with, both languages share the same memory locations for the variables.
To pass the address of a common block, simply pass the address of the first variable in the block, that is, pass the first variable by reference. The receiving C or C++ module should expect to receive a structure by reference.
In the following example, the C function initcb
receives
the address of a common block with the first variable named n
,
which it considers to be a pointer to a structure with three fields:
Fortran source code:
! INTERFACE SUBROUTINE initcb (BLOCK) !DEC$ ATTRIBUTES C :: initcb !DEC$ ATTRIBUTES REFERENCE :: BLOCK INTEGER BLOCK END SUBROUTINE END INTERFACE ! INTEGER n REAL(8) x, y COMMON /CBLOCK/n, x, y . . . CALL initcb( n )
C source code:
// struct block_type { int n; double x; double y; }; // void initcb( struct block_type *block_hed ) { block_hed->n = 1; block_hed->x = 10.0; block_hed->y = 20.0; }