Interlanguage Communication
The C and C++ compilers provide mechanisms for declaring external functions written in other languages. This enables the writing of portions of an application in C, C++, Fortran, or assembly language, which can be useful in cases where the other languages provide performance advantages or utilities not available in C or C++.
The C and C++ compilers provide mechanisms for declaring external functions written in other languages. This enables the writing of portions of an application in C, C++, Fortran, or assembly language, which can be useful in cases where the other languages provide performance advantages or utilities not available in C or C++.
Calls Between C and C++ Functions
- In Cray C++, the extern "C" linkage is required when declaring an external function that is written in Cray C or when declaring a Cray C++ function that is to be called from Cray C. Normally the compiler mangles function names to encode information about the function's prototype in the external name; this prevents direct access to these function names from a C function. The extern "C" keyword prevents the compiler from performing name mangling.
- The program must be linked using the CC command.
- The program's main routine must be C or C++ code compiled using the CC command.
Objects can be shared between C and C++. There are some Cray C++ objects that are not accessible to Cray C functions, such as classes. The following object types can be shared directly:
- Integral and floating types.
- Structures and unions that are declared identically in C and C++. In order for structures and unions to be shared, they must be declared with identical members in the identical order.
- Arrays and pointers to the above types.
C_add_func is called by the Cray C++ main program:
#include <iostream.h>
extern "C" int C_add_func(int, int);
int global_int = 123;
main()
{
int res, i;
cout << "Start C++ main" << endl;
/* Call C function to add two integers and return result. */
cout << "Call C C_add_func" << endl;
res = C_add_func(10, 20);
cout << "Result of C_add_func = " << res << endl;
cout << "End C++ main << endl;
}
#include <stdio.h>
extern int global_int;
int C_add_func(int p1, int p2)
{
printf("\tStart C function C_add_func.\n");
printf("\t\tp1 = %d\n", p1);
printf("\t\tp2 = %d\n", p2);
printf("\t\tglobal_int = %d\n", global_int);
return p1 + p2;
}
Start C++ main
Call C C_add_func
Start C function C_add_func.
p1 = 10
p2 = 20
global_int = 123
Result of C_add_func = 30
End C++ main
Call Fortran Functions and Subroutines from C or C++
- Fortran uses the call-by-address convention. C and C++ use the call-by-value convention, which means that only pointers should be passed to Fortran subprograms.
- Fortran arrays are in column-major order. C and C++ arrays are in row-major order. This indicates which dimension is indicated by the first value in an array element subscript.
- Single-dimension arrays of signed 32-bit integers and single-dimension arrays of 32-bit floating-point numbers are the only aggregates that can be passed as parameters without changing the arrays.
- Fortran character pointers and character pointers from Cray C and C++ are incompatible.
- Fortran logical values and the Boolean values from C and C++ are not fully compatible.
- External C and C++ variables are stored in common blocks of the same name, making them readily accessible from Fortran programs if the C or C++ variable is in uppercase.
- When declaring Fortran functions or objects in C or C++, the name must be specified in all uppercase letters, digits, or underscore characters and consist of 31 or fewer characters.
- In Cray C, Fortran functions can be declared using the fortran keyword. The fortran keyword is not available in Cray C++. Instead, Fortran functions must be declared by specifying extern "C".
Because Fortran subroutines expect arguments to be passed by pointers rather than by value, C and C++ functions called from Fortran subroutines must pass pointers rather than values.
All argument passing in Cray C is strictly by value. To prepare for a function call between two Cray C functions, a copy is made of each actual argument. A function can change the values of its formal parameters, but these changes cannot affect the values of the actual arguments. It is possible, however, to pass a pointer. (All array arguments are passed by this method.) This capability is analogous to the Fortran method of passing arguments.
In addition to passing by value, Cray C++ also provides passing by reference.
| A[0][0] | A[0][1] |
| A[1][0] | A[1][1] |
| A[2][0] | A[2][1] |
A[0][0] A[0][1] A[1][0] A[1][1] A[2][0] A[2][1]| A(1,1) | A(2,1) | A(3,1) |
| A(1,2) | A(2,2) | A(3,2) |
A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2)When an array is shared between Cray C, C++, and Fortran, its dimensions are declared and referenced in C and C++ in the opposite order in which they are declared and referenced in Fortran. Arrays are zero-based in C and C++ and are one-based in Fortran, so in C and C++, subtract 1 from the array subscripts that would normally be used in Fortran.
int a[2][3];| Fortran | C or C++ |
|---|---|
| A(1,1) | A[0][0] |
| A(2,1) | A[0][1] |
| A(3,1) | A[0][2] |
| A(1,2) | A[1][0] |
| A(2,2) | A[1][1] |
| A(3,2) | A[1][2] |
Logical and character data need special treatment for calls between C or C++ and Fortran. Fortran has a character descriptor that is incompatible with a character pointer in C and C++. The techniques used to represent logical (Boolean) values also differ between Cray C, C++, and Fortran.
| Macro | Description |
|---|---|
| _btol | Conversion utility that converts a 0 to a Fortran logical .FALSE. and a nonzero value to a Fortran logical .TRUE. |
| _ltob | Conversion utility that converts a Fortran logical .FALSE. to a 0 and a Fortran logical .TRUE. to a 1. |
The following example demonstrates how external C and C++ variables are accessible in Fortran named common blocks. It shows a C or C++ function calling a Fortran subprogram, the associated Fortran subprogram, and the associated input and output.
In this example, the C or C++ structure _st is accessed in the Fortran subprogram as common block ST. The Fortran common block ST will be converted to lower case with a trailing underscore added.
The name of the structure and the converted Fortran common block name must match. The C and C++ structure member names and the Fortran common block member names do not have to match, as is shown in this example.
#include <stdio.h>
struct
{
int i;
double a[10];
long double d;
} _st;
main()
{
int i;
/* initialize struct _st */
_st.I = 12345;
for (i = 0; i < 10; i++)
_st.a[i] = i;
_st.d = 1234567890.1234567890L;
/* print out the members of struct _st */
printf("In C: _st.i = %d, _st.d = %20.10Lf\n", _st.i, _st.d);
printf("In C: _st.a = ");
for (i = 0; i < 10; i++)
printf("%4.1f", _st.a[i]);
printf("\n\n");
/* call the fortran function */
FCTN();
}C *********** Fortran subprogram (f.f): ***********
SUBROUTINE FCTN
COMMON /ST/STI, STA(10), STD
INTEGER STI
REAL STA
DOUBLE PRECISION STD
INTEGER I
WRITE(6,100) STI, STD
100 FORMAT ('IN FORTRAN: STI = ', I5, ', STD = ', D25.20)
WRITE(6,200) (STA(I), I = 1,10)
200 FORMAT ('IN FORTRAN: STA =', 10F4.1)
END% cc -c c.c
% ftn -c f.f
% ftn c.o f.o
% ./a.out
ST.i = 12345, ST.d = 1234567890.1234567890
In C: ST.a = 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
IN FORTRAN: STI = 12345, STD = .12345678901234567889D+10
IN FORTRAN: STA = 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0Fortran includes the concept of a common block. A common block is an area of memory that can be referenced by any program unit in a program. A named common block has a name specified in names of variables or arrays stored in the block. A blank common block, sometimes referred to as blank common, is declared in the same way, but without a name.There is no way to access blank common from C or C++ similar to accessing a named common block. However, a simple Fortran function can be written to return the address of the first word in blank common to the C or C++ program and then use that as a pointer value to access blank common.
Access Fortran blank common from C or C++ Code
#include <stdio.h>
struct st
{
float a;
float b[10];
} *ST;
#ifdef __cplusplus
extern "C" struct st *MYCOMMON(void);
extern "C" void FCTN(void);
#else
fortran struct st *MYCOMMON(void);
fortran void FCTN(void);
#endif
main()
{
int i;
ST = MYCOMMON();
ST->a = 1.0;
for (i = 0; i < 10; i++)
ST->b[i] = i+2;
printf("\n In C and C++\n");
printf(" a = %5.1f\n", ST->a);
printf(" b = ");
for (i = 0; i < 10; i++)
printf("%5.1f ", ST->b[i]);
printf("\n\n");
FCTN();
}
The following Fortran subroutine uses blank common and is called from main() above.
SUBROUTINE FCTN
COMMON // STA,STB(10)
PRINT *, "IN FORTRAN"
PRINT *, " STA = ",STA
PRINT *, " STB = ",STB
STOP
END
INTEGER(KIND=8) FUNCTION MYCOMMON()
COMMON // A
MYCOMMON = LOC(A)
RETURN
END
The previous Cray C and Fortran code is executed by the following commands, and produces the output shown:
% cc -c c1.c
% ftn -c f2.f
% ftn c1.o f1.o
% ./a.out
In C and C++
a = 1.0
b = 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0
IN FORTRAN
STA = 1.
STB = 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.
STOP
Call a Fortran Program from Cray C++
Here is an example of a Cray C function that calls a Fortran subprogram. The Fortran subprogram example follows the Cray C function example, and the input and output from this sequence follows the Fortran subprogram example.
/* C program (main.c): */
#include <stdio.h>
#include <string.h>
#include <fortran.h>
/* Declare prototype of the Fortran function. Note the last */
/* argument passes the length of the first argument. */
fortran double FTNFCTN (char *, int *, int);
double FLOAT1 = 1.6;
double FLOAT2; /* Initialized in FTNFCTN */
main()
{
int clogical, ftnlogical, cstringlen;
double rtnval;
char *cstring = "C Character String";
/* Convert clogical to its Fortran equivalent */
clogical = 1;
ftnlogical = _btol(clogical);
/* Print values of variables before call to Fortran function */
printf(" In main: FLOAT1 = %g; FLOAT2 = %g\n",
FLOAT1, FLOAT2);
printf(" Calling FTNFCTN with arguments:\n");
printf(" string = \"%s\"; logical = %d\n\n", cstring, clogical);
cstringlen = strlen(cstring);
rtnval = FTNFCTN(cstring, &ftnlogical, cstringlen);
/* Convert ftnlogical to its C equivalent */
clogical = _ltob(&ftnlogical);
/* Print values of variables after call to Fortran function */
printf(" Back in main: FTNFCTN returned %g\n", rtnval);
printf(" and changed the two arguments:\n");
printf(" string = \"%.*s\"; logical = %d\n",
cstringlen, cstring, clogical);
}
C Fortran subprogram (ftnfctn.f):
FUNCTION FTNFCTN(STR, LOG)
REAL FTNFCTN
CHARACTER*(*) STR
LOGICAL LOG
COMMON /FLOAT1/FLOAT1
COMMON /FLOAT2/FLOAT2
REAL FLOAT1, FLOAT2
DATA FLOAT2/2.4/ ! FLOAT1 INITIALIZED IN MAIN
C PRINT CURRENT STATE OF VARIABLES
PRINT*, ' IN FTNFCTN: FLOAT1 = ', FLOAT1,
1 ';FLOAT2 = ', FLOAT2
PRINT*, ' ARGUMENTS: STR = "', STR, '"; LOG = ', LOG
C CHANGE THE VALUES FOR STR(ING) AND LOG(ICAL)
STR = 'New Fortran String'
LOG = .FALSE.
FTNFCTN = 123.4
PRINT*, ' RETURNING FROM FTNFCTN WITH ', FTNFCTN
PRINT*
RETURN
END% cc -c main.c
% ftn -c ftnfctn.f
% ftn main.o ftnfctn.o
% ./a.out
In main: FLOAT1 = 1.6; FLOAT2 = 2.4
Calling FTNFCTN with arguments:
string = "C Character String"; logical = 1
IN FTNFCTN: FLOAT1 = 1.6; FLOAT2 = 2.4
ARGUMENTS: STR = "C Character String"; LOG = T
RETURNING FROM FTNFCTN WITH 123.4
Back in main: FTNFCTN returned 123.4
and changed the two arguments:
string = "New Fortran String"; logical = 0#include <iostream>
using namespace std;
extern "C" int fortran_add_ints_(int *arg1, int &arg2);
main()
{
int num1, num2, res;
cout << "Start C++ main" << endl << endl;
//Call FORTRAN function to add two integers and return result.
//Note that the second argument is a reference parameter so
//it is not necessary to take the address of the
//variable num2.
num1 = 10;
num2 = 20;
cout << "Before Call to FORTRAN_ADD_INTS" << endl;
res = fortran_add_ints_(&num1, num2);
cout << "Result of FORTRAN Add = " << res << endl << endl;
cout << "End C++ main" << endl;
}INTEGER FUNCTION FORTRAN_ADD_INTS(Arg1, Arg2)
INTEGER Arg1, Arg2
PRINT *," FORTRAN_ADD_INTS, Arg1,Arg2 = ", Arg1, Arg2
FORTRAN_ADD_INTS = Arg1 + Arg2
ENDStart C++ main
Before Call to FORTRAN_ADD_INTS
FORTRAN_ADD_INTS, Arg1,Arg2 = 10, 20
Result of FORTRAN Add = 30
End C++ mainCalling a C or C++ Function from Fortran
- Standard Fortran/C Interoperability
- Portable Interoperability Mechanism
For more information about C interoperability, see the current Fortran standard. The ISO_C_BINDING module provides interoperability between Fortran intrinsic types and C types. The ISO_C_BINDING module provides named constants which can be used as KIND type parameters, compatible with C types. In addition to the named constants required by the Fortran standard, Cray compiler provides, as an extension, definitions for 128-bit floating, and complex types. C_FLOAT128 and C_FLOAT128_COMPLEX correspond to C types __float128 and __float128 complex. For more information about C interoperability, see the current Fortran standard.
- The Cray C++ function must be declared with extern "C" linkage.
- The program must be linked using the CC() command.
- The program's main routine must be C or C++ code compiled using the CC command.
Call a C function from Fortran
C Fortran program (main.f):
PROGRAM MAIN
REAL CFCTN
COMMON /FLOAT1/FLOAT1
COMMON /FLOAT2/FLOAT2
REAL FLOAT1, FLOAT2
DATA FLOAT1/1.6/ ! FLOAT2 INITIALIZED IN cfctn.c
LOGICAL LOG
CHARACTER*24 STR
REAL RTNVAL
C INITIALIZE VARIABLES STR(ING) AND LOG(ICAL)
STR = 'Fortran Character String'
LOG = .TRUE.
C PRINT VALUES OF VARIABLES BEFORE CALL TO C FUNCTION
PRINT*, 'In main.f: FLOAT1 = ', FLOAT1,
1 '; FLOAT2 = ', FLOAT2
PRINT*, 'Calling cfctn.c with these arguments: '
PRINT*, 'LOG = ', LOG
PRINT*, 'STR = ', STR
RTNVAL = CFCTN(STR, LOG)
C PRINT VALUES OF VARIABLES AFTER CALL TO C FUNCTION
PRINT*, 'Back in main.f:: cfctn.c returned ', RTNVAL
PRINT*, 'and changed the two arguments to: '
PRINT*, 'LOG = ', LOG
PRINT*, 'STR = ', STR
END PROGRAM% ftn -c main.f
/* C function (cfctn.c) */
#include <fortran.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
float FLOAT1; /* Initialized in MAIN */
float FLOAT2 = 2.4;
/* The slen argument passes the length of string in str */
float cfctn_(char * str, int *log, int slen)
{
int clog;
float rtnval;
char *cstring;
/* Convert log passed from Fortran MAIN */
/* into its C equivalent */
cstring = malloc(slen+1);
strncpy(cstring, str, slen);
cstring[slen] = '\0';
clog = _ltob(log);
/* Print the current state of the variables */
printf(" In CFCTN: FLOAT1 = %.1f; FLOAT2 = %.1f\n",
FLOAT1, FLOAT2);
printf(" Arguments: str = '%s'; log = %d\n",
cstring, clog);
/* Change the values for str and log */
strncpy(str, "C Character String ", 24);
*log = 0;
rtnval = 123.4;
printf(" Returning from CFCTN with %.1f\n\n", rtnval);
return(rtnval);
}% cc -c cfctn.c% % ftn -o interlang1 main.o cfctn.o% ./interlang1In main.f: FLOAT1 = 1.60000002 ; FLOAT2 = 2.4000001
Calling cfctn.c with these arguments:
LOG = T
STR = Fortran Character String
In CFCTN: FLOAT1 = 1.6; FLOAT2 = 2.4
Arguments: str = 'Fortran Character String'; log = 1
Returning from CFCTN with 123.4
Back in main.f:: cfctn.c returned 123.400002
and changed the two arguments to:
LOG = F
STR = C Character StringFortran, C, C++ Interoperability
The Cray Compiler supports interoperability mechanisms specfied in the Fortran 2008 standard, ISO/IEC 1539-1:2010, and TS 29113 Further Interoperability of Fortran and C.
- Intrinsic Types
- The Fortran intrinsic module
ISO_C_BINDINGprovides interoperability between Fortran intrinsic types and C types. TheISO_C_BINDINGmodule provides named constants which can be used asKINDtype parameters, compatible with C types. - Derived Types and Structures
- Use the
BINDattribute when creating an interoperable type:USE ISO_C_BINDING TYPE, BIND(C) :: THIS_TYPE . . . END TYPE THIS_TYPE - Global Variables
- Use the
BINDattribute with a common block declaration, or module variable:USE ISO_C_BINDING INTEGER(C_INT), BIND(C) :: EXTERN INTEGER(C_LONG) :: CVAR BIND(C, NAME='var') :: CVAR COMMON /A/ I, J REAL(C_FLOAT) :: I, J BIND(C) :: /A/ - Pointers
ISO_C_BINDINGprovides a derived type,c_ptr, that interoperates with any C pointer type. Also, Fortran named constantc_null_ptris equivalent to the C value NULL.- Subroutines and Function
- Declare a Fortran procedure with the BIND attribute. Procedure arguments must be of interoperable type. By default the Fortran compiler converts the procedure name to lower-case (
myfunction); this is the binding label, or corresponding name which is known to the C compiler.FUNCTION MYFUNCTION(X, Y), BIND(C)Specify a different binding label:A function result must be scalar and of interoperable type. A subroutine prototype must have a void result.FUNCTION MYFUNCTION(X, Y), BIND(C, NAME='C_Myfunction')
- C descriptors
- ISO_Fortran_binding.h defines C structure
CFI_cdesc_twhich facilitates using Fortran data objects from within a C function. - ISO_Fortran binding.h
- Contains additional C structure definitions and macro definitions to interoperate with an allocatable, or data pointer argument.
Interlanguage Communication Examples
Interlanguage Communication using Common Block/Global
// common_c.c : example of function called from common.f90
#include <stdio.h>
#include <stdlib.h>
#include <ISO_Fortran_binding.h>
// globals that match up to the common blocks in common.f90
float c_single;
struct common {
double var1;
int var2;
} multiple;
int c_int_array[100];
// c function called from Fortran
void global_var_common()
{
int i;
// just prints and sets the globals
printf(" In global_var_common\n");
printf(" c_single: %f\n", c_single);
printf(" multiple: %f, %d\n", multiple.var1, multiple.var2 );
printf(" c_int_array: %d, %d\n", c_int_array[0], c_int_array[99]);
c_single = 2 * c_single;
multiple.var1 = 77.77;
multiple.var2 = 17;
for(i=0; i<100; i++ ) {
c_int_array[i] = c_int_array[i] * 3;
}
} // end of global_var_common
! common.f90
! Needs common_c.c
program common_block
use, intrinsic :: iso_c_binding
! use check_error
implicit none
!
! declare the common blocks for c globals
! one with a single real variable
real(c_float) r_var
common /c_single/ r_var
! one with an integer array
integer i_array(100)
common / array / i_array
! one with two variables
real(c_double) :: var1
integer(c_int) :: var2
common / multiple / var1, var2
! do the bind c on the common blocks, renaming one
BIND(C,name="c_int_array") :: / array /
BIND(C) :: / multiple /, /c_single/
call sub1()
end program common_block
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine sub1( )
use, intrinsic :: iso_c_binding
! declare the common blocks for c globals
! one with a single real variable
real(c_float) r_var
common /c_single/ r_var
! one with an integer array
integer i_array(100)
common / array / i_array
real(c_double) var1
integer(c_int) var2
common / multiple / var1, var2
! do the bind c on the common blocks, renaming array
BIND(C,name="c_int_array") :: / array /
BIND(C) :: / multiple /, /c_single/
interface
subroutine global_var_common( ) bind(c)
use,intrinsic :: iso_c_binding
implicit none
end subroutine global_var_common
end interface
r_var = -99.3
var1 = 88.88
var2 = -13
i_array = [(i,i=1,100)]
! call the c function
call global_var_common( )
print *, "In sub1"
print *, " r_var : ", r_var
print *, " var1 : ", var1
print *, " var2 : ", var2
print *, " array : ", i_array(1), i_array(100)
end subroutine
Interlanguage Communication using Derived Structure
// c program that calls the Fortran subroutine with struct argument, f2008 C.11.3
//*********************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <ISO_Fortran_binding.h>
// declare the structure type
struct pass {
int lenc, lenf;
float *c, *f;
};
// prototype for the Fortran function
void simulation(long alpha, double *beta, long *gamma, double delta[], struct pass *arrays);
// program that calls the Fortran subroutine
int main ( )
{
int i;
long alpha, gamma;
double beta, delta[100];
struct pass arrays;
alpha = 1234L;
gamma = 5678L;
beta = 12.34;
for(i=0; i<100; i++ ) {
delta[i] = i+1;
}
// fill in some of the structure
arrays.lenc = 100;
arrays.lenf = 0;
arrays.c = (float *) malloc( 100*sizeof(float) );
arrays.f = NULL;
for(i=0; i<100; i++ ) {
arrays.c[i] = 2*(i+1);
}
// reference the Fortran subroutine
simulation(alpha, &beta, &gamma, delta, &arrays);
printf(" After simulation\n");
printf(" alpha: %d, beta: %f\n", alpha, beta );
printf(" gamma: %d\n", gamma );
printf(" arrays.lenc: %d\n", arrays.lenc);
printf(" arrays.c[0],[arrays.lenc-1],: %f, %f\n", arrays.c[0], arrays.c[arrays.lenc-1]);
printf(" arrays.lenf: %d\n", arrays.lenf);
printf(" arrays.f[0],[arrays.lenf-1],: %f, %f\n", arrays.f[0], arrays.f[arrays.lenf-1]);
} // end of main
! Example derived type/structure interoperability, f2008 C.11.3
!**************************************************************
subroutine simulation(alpha, beta, gamma, delta, arrays) bind(c)
use, intrinsic :: iso_c_binding
implicit none
integer (c_long), value :: alpha
real (c_double), intent(inout) :: beta
integer (c_long), intent(out) :: gamma
real (c_double),dimension(*),intent(in) :: delta
type, bind(c) :: pass
integer (c_int) :: lenc, lenf
type (c_ptr) :: c, f
end type pass
type (pass), intent(inout) :: arrays
real (c_float), allocatable, target, save :: eta(:)
real (c_float), pointer :: c_array(:)
integer i
print *, "In simulation"
print *, " alpha: ", alpha, ", beta: ", beta
print *, " delta(1),(100): ", delta(1), delta(100)
! associate c_array with an array allocated in c
call c_f_pointer (arrays%c, c_array, [arrays%lenc])
print *, " c_array(1),(arrays%lenc): ", c_array(1), c_array(arrays%lenc)
! allocate an array and make it available in c
arrays%lenf = 100
allocate (eta(arrays%lenf))
arrays%f = c_loc(eta)
eta = [(i*3,i=1,arrays%lenf)]
! change argument values
c_array = c_array * 2.0
gamma = 77
beta = -55.66
end subroutine simulation
Interlanguage Communication using Module
// c function called from module.f90
#include <stdio.h>
#include <stdlib.h>
#include <ISO_Fortran_binding.h>
// globals that match up to the module variables in module.f90
float r_var;
double var1;
int var2;
int c_int_array[100];
// c function called from Fortran
void global_var_module()
{
int i;
// just prints and sets the globals
printf(" In global_var_module\n");
printf(" r_var : %f\n", r_var);
printf(" var1 : %f\n", var1 );
printf(" var2 : %d\n", var2 );
printf(" c_int_array: %d, %d\n", c_int_array[0], c_int_array[99]);
r_var = 2 * r_var;
var1 = 77.77;
var2 = 17;
for(i=0; i<100; i++ ) {
c_int_array[i] = c_int_array[i] * 3;
}
} // end of global_var_module
! Example of module/global variable interoperability.
! Needs c function from module_c.c
! ********************************************************************
module module_example_mod
use, intrinsic :: iso_c_binding
real(c_float) r_var
integer i_array(100)
real(c_double) :: var1
integer(c_int) :: var2
BIND(C,name="c_int_array") :: i_array
BIND(C) :: r_var, var1, var2
end module module_example_mod
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program module_example
use module_example_mod
implicit none
call sub1()
end program module_example
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine sub1( )
use module_example_mod
interface ! for the c function
subroutine global_var_module( ) bind(c)
use,intrinsic :: iso_c_binding
implicit none
end subroutine global_var_module
end interface
r_var = -99.3
var1 = 88.88
var2 = -13
i_array = [(i,i=1,100)]
! call the c function
call global_var_module( )
print *, "In sub1"
print *, " r_var : ", r_var
print *, " var1 : ", var1
print *, " var2 : ", var2
print *, " array : ", i_array(1), i_array(100)
end subroutine