Using Common External Data in Mixed-Language Programming

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:

Using Global Variables in Mixed-Language Programming

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.)

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:

Accessing Common Blocks and C Structures Directly

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.

Passing the Address of a Common Block

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; }