Calling NAG Fortran Library Routines
(implementations compiled with Compaq Visual Fortran)
from C Language Programs Using the NAG C Header File
Ian Hounam
NAG Ltd, Oxford
© The Numerical Algorithms Group Ltd, Oxford UK. 2002
A header file containing the function prototypes can be included in the user's program to allow the C compiler to check argument passage. Such a header file has been created for the current NAG Fortran Library. This was done automatically from the Library source code in order to ensure its correctness. This document explains how to call Fortran routines from C using the NAG header file.
The information in this document is specific to NAG Library implementations compiled with Compaq Visual Fortran. The C Compiler used to test the conventions was Microsoft Visual C/C++.
DOUBLE PRECISION D double d;
INTEGER I int i;
LOGICAL L int l;
CHARACTER*n S char *s; int len_s; /* See below */
DOUBLE COMPLEX Z struct {double re,im;} z;
All arguments (except CHARACTER) are passed as pointers to a variable; this means that a constant must first be assigned to a variable and then the address of the variable passed.
As Fortran stores multi-dimension arrays in column major order whereas C stores in row major order, either
Character arguments are passed as two arguments
For example to call a routine called "NAGSUB" which in Fortran looks like this
SUBROUTINE NAGSUB(A,B,C)
CHARACTER A
CHARACTER*3 B
CHARACTER*5 C(2)
the C code looks like this.
extern void __stdcall NAGSUB(char* a, int len_a,
char *b, int len_b, char c[], int len_c);
main()
{
char a = 'a';
int len_a = 1;
char b[] = "abc";
int len_b = 3;
char c[2][6] = {"abcde", "fghij"};
int len_c = 5;
NAGSUB(&a, len_a, b, len_b, (char *)c, len_c);
}
Note that the char variables' declared length in the C program must allow space for the null termination in the C string.
The Fortran type DOUBLE COMPLEX (or COMPLEX*16) is provided in the NAG header files by the typedef "Complex", which expands to "struct {double re,im;}"
DOUBLE COMPLEX FUNCTION F(X)
DOUBLE COMPLEX X
has the following prototype:
extern void __stdcall f(Complex *, Complex *);
and a user callable function, e.g S01EAF, looks like this
extern void __stdcall S01EAF(Complex *return_value, const Complex *z,
int *ifail);
int array[] /* 2 dimension */
and for 3 dimensions:
double array[] /* 3 dimension */
The prototype for a hypothetical NAG Fortran routine with a 2 dimensional DOUBLE PRECISION array argument would look like this:
extern void __stdcall NAGSUB(double[] /* 2 dimensions */);
A simple program to call this routine might look like this:
main ()
{
double p[2][2];
NAGSUB((double *)p);
}
Note that we need to cast the 2 dimensional C array actual argument to (double *).
The example prototype below shows how to call a hypothetical NAG routine that takes a single subroutine argument. This user supplied subroutine takes a 2 dimension DOUBLE PRECISION array and an integer which specifies the leading dimension of the Fortran array.
extern void __stdcall NAGSUB(void (*f) (double[] /* 2 dimension */,
int *));
The C code for the user supplied function is listed below. The 2 dimension array is passed as a pointer to double and the code must carry out array indexing using the dimension information passed from Fortran. In this case, the macro P uses the leading dimension of the Fortran array, which is the trailing dimension of the C array, to index into the array p. The array p is only referenced through this macro.
void __stdcall fun(double p[], int *tdp)
{
#define P(I,J) p[(I) + (*tdp)*(J)]
P(0,0) = 0.0;
P(1,1) = 1.0;
}
The main function looks like this:
main ()
{
void __stdcall fun(double p[], int *tdp);
NAGSUB(fun);
}
Example 2 below shows a complete program that illustrates these concepts.