NAG Numerical Libraries - Microsoft C ++

NAG DLLs and Microsoft C ++

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.

The NAG Fortran DLLs may be used with care from within a C or C++ environment. To assist the user make the mapping between Fortran and C types, a set of C Header files is provided in the user's program to allow the C compiler to check argument passage. Such a Header file has been created for the NAG Fortran Library. This was done automatically from the library source code in order to ensure its correctness.

It is recommended that users wishing to use a Fortran DLL routine cut and paste the relevant section of the appropriate file into their C applications. Alternatively, the NAG C Header file is provided in the Headers directory. Please refer to the technical documentation file techdoc.html, viewable with any Web Browser, for details on how to use the C Header file. Please click here for information on how to call Fortran routines from C using the NAG C Header files.

Fortran and C have, by default, a different way of passing arguments and a different view on whether the calling program or the called program tidies up the stack. In any form of mixed language programming these calling conventions have to be unified. In this case the Visual C++ programmer must specify the STDCALL calling convention either by explicitly including the __stdcall keyword in the declarations of NAG routines and in the declarations and definitions of 'call-back’ functions, or by using the Microsoft Developer Studio to reset the calling convention linker option.

There are in addition different conventions adhered to by the C language from that of Fortran. For example, NAG Fortran routines assume that array indices start at 1, whereas the usual C convention is that indices start at 0. Care must also be taken with two-dimensional arrays. Fortran conventions stipulate, for example, that element (2,1) is next to element (1,1) in the physical storage of the array. C convention has element (1,2) next to (1,1) (i.e. Fortran stores by column, C by row). The result is that the C programmer often has to provide the transpose array to Fortran routines and to interpret returned array information accordingly.

C character strings and Fortran character strings are handled differently. In the Compaq Visual Fortran implementation a string argument is passed by value as a structure consisting of a 4-byte argument address, followed by the length of the string.

The following two examples illustrate the use of the NAG DLLs using Microsoft Visual C++, version 4.2.

Example 1: illustrating arrays and character strings

#include <stdio.h>
  #define CONST const
typedef struct { char *str; int val; } Fortran_character_arg;
  
  extern void __stdcall F01QCF(
    CONST int *m,
    CONST int *n,
    double a[ ],
    CONST int *lda,
    double zeta[ ],
    int *ifail
  );
  
  extern void __stdcall F01QDF(
    CONST Fortran_character_arg trans,
    CONST Fortran_character_arg wheret,
    CONST int *m,
    CONST int *n,
    double a[ ],
    CONST int *lda,
    CONST double zeta[ ],
    CONST int *ncolb,
    double b[ ],
    CONST int *ldb,
    double work[ ],
    int *ifail
  );
  
  /* Simplified example program for F01QDF */
  
  main( )
  {
    int i,ifail,j,m = 5,n = 3,ncolb = 2;
    int lda = m,ldb = m;
    Fortran_character_arg tr = {"Transpose",9};
    Fortran_character_arg se = {"Separate",8};
    /* Initialise arrays in column major order */
    static double a[3][5] =
      {
        2.0, 2.0, 1.6, 2.0, 1.2,
        2.5, 2.5, -0.4, -0.5, -0.3,
        2.5, 2.5, 2.8, 0.5, -2.9
      };
    static double b[2][5] =
      {
        1.1, 0.9, 0.6, 0.0, -0.8,
        0.0, 0.0, 1.32, 1.1, -0.26
      };
    double work[2],zeta[3];
  
    printf("F01QDF Example Program Results\n\n");
    ifail = 0;
    F01QCF(&m,&n,(double *)a,&lda,zeta,&ifail);
    ifail = 0;
    F01QDF(tr,se,&m,&n,(double *)a,&lda,zeta,&ncolb,(double
  *)b,&ldb,work,&ifail);
    printf("Matrix  Q'*B\n");
    for (i=0; i<m; i++)
      {
        for (j=0; j<ncolb; j++)
          {
            printf("%f ",b[j][i]);
          }
        printf("\n");
      }
    return 0;
  }

Example 2: illustrating the use of functions

#include <math.h>
  #include <stdio.h>
  #define CONST const
  typedef struct { char *str; int val; } Fortran_character_arg;
  extern void __stdcall C05AJF(
    double *x,
    CONST double *eps,
    CONST double *eta,
    double (__stdcall *f)(double *),
    CONST int *nfmax,
    int *ifail
  );
  
  static double __stdcall f(double *);
  
  main( )
  {
    double eps, eta, x;
    int ifail, k, nfmax;
  
    printf("C05AJF Example Program Results\n\n");
    for (k=1; k<=2; k++)
      {
        eps = k==1 ? 0.1e-3 : 0.1e-4;
        x = 1.0;
        eta = 0.0;
        nfmax = 200;
        ifail = 1;
        C05AJF(&x,&eps,&eta,f,&nfmax,&ifail);
        if (ifail==0)
          printf("With eps = %e   root = %f\n",eps,x);
        else
          {
            printf("ifail = %d\n",ifail);
            if (ifail==3 | ifail==4)
              printf("With eps = %e final value = %f\n",eps,x);
          }
      }
    return 0;
  }
  static double __stdcall f(double *x)
  {
    return exp(-*x) - *x;
  }

Both of these programs work from within the Microsoft Developer Studio in the normal way. It must be remembered, however, that the user must set the calling convention to STDCALL.

Click here for further information on calling Fortran routines from C using the NAG C Header files.

Alternatively the NAG C Library provides over 400 user-callable functions. As with all NAG products, you can rely on the fact that these functions are of the highest quality, fully tested and certified. Click here for information on using C-based DLLs.