Fortran common blocks and C/C++ structures


When you want to access variables in Fortran common blocks from C/C++ you need to define structs in C/C++ that matches the common blocks. This, of course, also provides means to manipulate the common blocks in Fortran in order to transfer information to your C/C++ code.

Important. Read this carefully, it can save you a lot of time.
Note that the order of the variables, and array sizes, within the common block and structure is very important. When the linker reaches a common block or structure definition it assigns a memory area for the whole block of variables. The variables are referenced consecutively within this memory area. A mismatch in the common block and the structure definitions will naturally lead to conflicting variable references.


Example

Fortran definition of a common block:

COMMON /LUJETS/ N,K(4000,5),P(4000,5),V(4000,5)
SAVE /LUJETS/


Corresponding straightforward C/C++ struct definition. (Note the reversion of array indices.)

extern “C” /* this line should be omitted in C */
{
extern struct {
int n; /* nof lines occupied in matrices below */
int k[5][4000]; /* k[0][i] status code KS */
/* k[1][i] particle code KF */
/* k[2][i] line nof parent particle/jet */
/* k[3][i] normally line nof 1st daugther */
/* k[4][i] normally line nof last daught. */
float p[5][4000]; /* p[0][i] p_x, momentum in Gev/c */
/* p[1][i] p_y, momentum in Gev/c */
/* p[2][i] p_z, momentum in Gev/c */
/* p[3][i] E, energy in Gev */
/* p[4][i] m, mass in Gev/c^2 */
/* when Q^2=-m^2 >0, p[4][i]=-Q */
float v[5][4000]; /* v[0][i] x position of vertex, in mm */
/* v[1][i] y position of vertex, in mm */
/* v[2][i] z position of vertex, in mm */
/* v[3][i] time of production, in mm/c */
/* v[4][i] proper lifetime, in mm/c */
} lujets_;
}


Variant C/C++ struct definition. Here a struct eventrecord is defined, and then used to declare the variables lujets_ and another_eventrecord. Later a statement like another_eventrecord=lujets_; can be issued. (Note the reversion of array indices.)

struct eventrecord {
int n; /* nof lines occupied in matrices below */
int k[5][4000]; /* k[0][i] status code KS */
/* k[1][i] particle code KF */
/* k[2][i] line nof parent particle/jet */
/* k[3][i] normally line nof 1st daugther */
/* k[4][i] normally line nof last daught. */
float p[5][4000]; /* p[0][i] p_x, momentum in Gev/c */
/* p[1][i] p_y, momentum in Gev/c */
/* p[2][i] p_z, momentum in Gev/c */
/* p[3][i] E, energy in Gev */
/* p[4][i] m, mass in Gev/c^2 */
/* when Q^2=-m^2 >0, p[4][i]=-Q */
float v[5][4000]; /* v[0][i] x position of vertex, in mm */
/* v[1][i] y position of vertex, in mm */
/* v[2][i] z position of vertex, in mm */
/* v[3][i] time of production, in mm/c */
/* v[4][i] proper lifetime, in mm/c */
};

extern “C” /* this line should be omitted in C */
{
extern struct eventrecord lujets_;
}
struct eventrecord another_eventrecord;
/* another_eventrecord could (should?) be a local variable
within the C/C++ code */