NAG C Header Files

Calling NAG Fortran Library Routines from C Language Programs
Using the NAG C Header Files on
Unix Systems

Ian Hounam

NAG Ltd, Oxford

© The Numerical Algorithms Group Ltd, Oxford UK. 2002

1 Introduction

A great number of systems allow the C programmer to call other language routines. Indeed the ANSI standard definition of C provides a powerful argument checking facility that, given the correct definition of function prototypes, can facilitate cross language communication between C and, say, Fortran.

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 and the current NAG Graphics 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. Note that if __STDC__ is not defined, no argument checking will be carried out.

2 Argument Types

The table below lists the mapping between relevant Fortran and C argument and function types.
   DOUBLE PRECISION D       double d;
   INTEGER I                int i;
   LOGICAL L                int l;
   CHARACTER*n S            char s[n];
   DOUBLE COMPLEX Z         struct {double re,im;} z;
All arguments 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

  1. the C routine must store and manipulate the transpose of the problem matrix, or
  2. the C routine must transpose the matrix before and after calling the Fortran routine.
Fortran CHARACTER type is different to C null terminated strings so that the actual length of the string must be passed as an extra argument.

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 nagsub_(char* a, char *b, char c[],
                     int len_a, int len_b, 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, b, (char *)c, len_a, len_b, 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 HP-UX 64 bit compiler uses long instead of int for the hidden length argument.

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

3 Subroutines and Functions

Fortran subroutines are declared as void functions in C.

Procedure arguments, i.e. function or subroutine names, are passed by address in the normal C manner.

4 Complex functions

4.1 Sun Solaris (32 bit implementation)

The Sun 32 bit Fortran compiler uses the de facto standard of some years ago. Fortran DOUBLE COMPLEX functions on Suns are actually implemented as C void functions with an extra first argument which is a pointer to the result e.g.
      DOUBLE COMPLEX FUNCTION F(X)
      DOUBLE COMPLEX X
has the following prototype:
      extern void f_(Complex *,Complex *);
and a user callable function, e.g S01EAF, looks like this
extern void s01eaf_(Complex *return_value,const Complex *z,int *ifail);

4.2 HP-UX, NAGWare f95 Compiler and Sun Solaris (64 bit implementation)

With the HP-UX, NAGWare Fortran compilers and Sun Solaris (64 bit implementation), DOUBLE COMPLEX FUNCTIONs return a structure identical to the "Complex" typedef in the NAG C Header File.

Note that the NAGWare compiler has an option to use the de facto standard described above, but this is not used in the NAG Fortran Library implementations.

The prototype for the user supplied function F with HP-UX or NAGWare is the following.

Complex (*f)(Complex *)
and a user callable function, e.g S01EAF, looks like this
extern Complex s01eaf_(const Complex *z,int *ifail);

4.3 DEC Alpha Unix, IBM AIX and Silicon Graphics

With the native Fortran compilers on DEC Alpha Unix, IBM AIX and Silicon Graphics, the C programmer wishing to access Fortran DOUBLE COMPLEX FUNCTIONs has real problems. The conventions used by the native Fortran compilers on these systems do not allow the C programmer to access the return value of DOUBLE COMPLEX FUNCTIONs directly because the DOUBLE COMPLEX return value is stored in registers that do not map to any C data type.

One solution is to use the NAGWare Compiler implementation of the NAG Fortran Library, see above.

As it is impossible to access the return value of a DOUBLE COMPLEX FUNCTION from C, another solution is to write a Fortran "jacket" routine to convert the DOUBLE COMPLEX FUNCTION to a SUBROUTINE with an extra initial argument containing a pointer to the return value. The "jacket" routine then calls S01EAF.

For example to call S01EAF, write a jacket routine called S01EAFJ which would have the following prototype.

extern void s01eafj_(Complex *ret_val, CONST Complex *z,
                     int *ifail);
The jacket routine is then called from the C program rather than S01EAF.
      SUBROUTINE S01EAFJ(RET_VAL, Z, IFAIL)
      DOUBLE COMPLEX RET_VAL, Z, S01EAF
      INTEGER IFAIL
      RET_VAL = S01EAF(Z, IFAIL)
      END
This routine can be compiled and linked with the C files and NAG Fortran Library in the normal way.

Similar jacket routines can be written for user supplied functions.

The supplied C Header files do not contain prototypes for these jacket functions. Use the "Standard Unix" version of the C Header File on these systems and modify the prototypes appropriately.

5 Character functions

A character function is implemented as a void function with two extra arguments added to the start of the argument list, the first is a pointer to the returned string and the second its length.

e.g.

      CHARACTER*10 FUNCTION F(I)
is called thus:
     extern void f_(char *,int,int *);
      char c[10];
      int clen = 10,i;
      f_(&c,clen,&i)

The HP-UX 64 bit compiler uses long instead of int for the hidden length argument.

6 Routine Names

Some Unix systems require the addition of an underscore to the name of Fortran routines called from C. e.g. X01AAF becomes x01aaf_.

7 Multi-Dimension Arrays

There is no syntax in the C language to specify an arbitrary array dimension and it is not possible to know in advance the dimensions of the arrays in your program. The best that the C Header Files can do is to declare the multi-dimensional arrays as one dimension arrays with a comment stating the actual number of dimensions, e.g. for 2 dimensions:
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 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 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 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 fun(double p[], int *tdp);
  nagsub_(fun);
}
Example 2 below shows a complete example program that illustrates these concepts.

8 Non-ANSI compliant Compilers

The NAG C header files can be used with compilers that do not support the ANSI Standard function prototypes. On these systems the conditional compilation preprocessor directives present in the header files result in a normal Kernighan and Ritchie function definition. Note that with such a compiler no argument checking will be carried out.

9 C++ Compilers

The C Header files contain an 'extern "C"' declaration for C++ compilers, i.e.
#ifdef __cplusplus
extern "C" {
#endif
(with a matching "}" at the end of the file)

10 Which Version of the NAG C Header Files Should I Use?

Some common platforms are listed in the table below. For an explanation of the text in the "Complex Functions" column see the section on Complex Functions above.

Platform Underscore Complex Functions
All NAGWare f95 Implementations Yes Complex Functions
DEC Alpha Unix Yes Standard Unix plus jacket
HP9000/700 32 bit implementation Both Complex Functions
HP9000/700 64 bit implementation Yes Use specific HP64 Header File
IBM AIX No Standard Unix plus jacket
Silicon Graphics Yes Standard Unix plus jacket
Sun Solaris 32 bit implementation Yes Standard Unix
Sun Solaris 64 bit implementation Yes Complex Functions

Note: "Both" in the "Underscore" column means that the NAG Fortran Library is supplied in two forms; with and without underscores. Use the C Header File appropriate to the library installed on your system.

The graphics library does not contain the complex data type, so the only issue is whether routine names have an underscore or not. For platforms with "Both" in the "Underscore" column above, please refer to local documentation (or failing this trial and error may be used) to find the correct convention for your graphics library.

11 Linking your program

It is always necessary to link your program with the Fortran run time library routines. This can most easily be achieved on most Unix systems by linking using the f77 command, not cc or ld. For example,
cc -c myprog.c
f77 -o myprog myprog.o -lnag
On some systems this will not work and in some circumstances it is necessary to link using ld or cc. In which case it is necessary to specify the Fortran run time libraries in the load command. The libraries may be documented in the f77 man page or, failing that, the commands generated by the compiler driver may be viewed using the -v, -dryrun or -# options to display the ld command line.

13 Examples

All the examples below are written in ANSI standard C; minor changes to remove function prototypes will be necessary for non-ANSI compilers. The examples are translations of NAG Fortran Library example programs into C. Where the Fortran code reads data, this data is coded directly into the initialisation of the C variables to make self-contained programs with no need for data files. Please refer to the NAG Fortran Library documentation for details of these example programs.

13.1 Example 1

This example shows how to call C05AJF using a procedure parameter, the function "f".

C05AJF Example Program.

13.2 Example 2

This example illustrates the use of two dimensional arrays in user supplied functions in the NAG Fortran Library routine D03PCF.

D03PCF Example Program

13.3 Example 3

This example illustrates the specification of two dimensional arrays in column major order in the C translation of the E04NFF example program. Results are printed by the NAG routine.

E04NFF Example Program

13.4 Example 4

The Fortran Library routine F01CTF is called with the matrices in the natural C row major order. The arguments TRANSA and TRANSB are used to specify that the matrices should be transposed. The result matrix is then transposed back to row major order using F01CRF. This example also illustrates character string arguments.

F01CTF Example Program

13.5 Example 5

DGBTRS is called with one matrix specified in column major order. Another matrix is loaded with its data using a macro to define the Fortran matrix ordering. Results are printed using X04CAF. This example also illustrates character string arguments.

DGBTRS/F07BEF Example Program



© The Numerical Algorithms Group Ltd, Oxford UK. 2002