How can I call CERNLIB routines from C or C++ ?


General

There are several methods of how to call FORTRAN (most CERN library functions are written in FORTRAN) from a C main program or subroutine. A very good and comprehensive overview of general methods can be found in the article Interfacing Fortran and C (PS) by A.Nathaniel in the CERN Computing Newsletter 217 (PS).

But the simplest way is surely to use the cfortran.h package. The complete documentation is in cfortran.doc in ASCII version, but it is strongly recommended to read the HTML version which is much easier to read.

Interface to CERN Library routines

To interface the CERN library FORTRAN Routines from C, ready-made header files exploiting cfortran.h are available. They are stored in

 /cern/pro/include/cfortran
 
or are available using anonymous ftp from

 asisftp.cern.ch:/cernlib/share/pro/include
 

To call a (FORTRAN) CERN library routine from C, you have to do the following steps:

  1. Include in you C files the following header files:
     #include "cfortran.h"
     #include "hbook.h"   /* if you use hbook routines e.g. */
     
  2. Call the fortran routine with "FORTRAN" style parameters (call by value), routine name in capitals:
     main(){
            real xmin,xmax;
            integer ncha;
            HLIMIT(1000);
            .
            .
            HBOOK1(100,"test spectrum",ncha,xmin,xmax,0);
            .
            .
     }
     
  3. Compile flags for C programs:

    1. HP:
       cc -c -Dextname -Ae -I/cern/pro/include/cfortran cfilename.c
       fort77 +ppu -c ffilename.f
       fort77 +ppu cfilename.o ffilename.o `cernlib packlib ...` ... -o outfilename
       
    2. LINUX:
       gcc -c -Df2cFortran -I/cern/pro/include/cfortran cfilename.c
       g77 -c ffilename.f
       g77 cfilename.o ffilename.o `cernlib packlib ...` ... -o outfilename
       
    3. AIX:
       xlc -c -Dextname -I/cern/pro/include/cfortran cfilename.c
       xlf -qextname -c ffilename.f
       xlf -qextname cfilename.o ffilename.o `cernlib packlib ...` ... -o outfilename
       
    4. DIGITAL UNIX/ OSF:
       cc -c -Dextname -I/cern/pro/include/cfortran cfilename.c
       f77  -c ffilename.f
       f77 -nofor_main cfilename.o ffilename.o `cernlib packlib ...` ... -o outfilename
       
    5. SUN/ Solaris:
       cc -c -I/cern/pro/include/cfortran cfilename.c
       f77  -c ffilename.f
       f77 cfilename.o ffilename.o `cernlib packlib ...` ... -o outfilename
       
    6. VMS:
       cc /INCLUDE=CERN_ROOT:[INCLUDE] cfilename.c
       fortran ffilename.FOR
       link/exe=outfilename cfilename,ffilename, ...
       
  4. Compile flags for C++ programs:

    1. LINUX:
       g++ -c cfilename.cpp -Df2cFortran -I/cern/pro/include/cfortran
       g++ -o outfilename cfilename.o `cernlib packlib,mathlib` -lg2c -lm
       
    2. DIGITAL UNIX/ OSF:
       cxx -c cfilename.cpp -std strict_ansi -msg_disable dollarusedid -Dextname -I/cern/pro/include/cfortran
       cxx -o outfilename cfilename.o `cernlib packlib,mathlib` -lfor -lm
       
    3. HP:
       aCC -c cfilename.cpp -Aa +DAportable -Dextname -I/cern/pro/include/cfortran
       aCC -o outfilename cfilename.o `cernlib packlib,mathlib` -lm
       
    4. AIX:
       xlC -c cfilename.cpp -Dextname -I/cern/pro/include/cfortran
       xlC -o outfilename cfilename.o `cernlib packlib,mathlib` -lxlf90 -lxlf -lm
       
    5. SUN:
       CC -c cfilename.cpp -I/cern/pro/include/cfortran
       CC -o outfilename cfilename.o `cernlib packlib,mathlib` -lM77 -lF77 -lsunmath -lm
       

Examples

The following examples show how to use this interface for hbook or minuit:

They have been compiled, linked and run with the following commands (using the first code example)

  1. HP:
     cc -c -Dextname -Ae -I/cern/pro/include/cfortran chbook-example.c
     fort77 +ppu chbook-example.o `cernlib packlib,mathlib` -o chbook-example
     ./chbook-example
    
     
  2. LINUX:
     gcc -c -Df2cFortran -I/cern/pro/include/cfortran chbook-example.c
     g77 chbook-example.o `cernlib packlib,mathlib` -o chbook-example
     ./chbook-example
    
     
  3. AIX:
     xlc -c -Dextname -I/cern/pro/include/cfortran chbook-example.c
     xlf -qextname chbook-example.o `cernlib packlib,mathlib` -o chbook-example
     ./chbook-example
    
     
  4. DIGITAL UNIX /(former) OSF:
     cc -c -Dextname -I/cern/pro/include/cfortran chbook-example.c
     f77 -nofor_main chbook-example.o `cernlib packlib,mathlib` -o chbook-example
     ./chbook-example
    
     
  5. VMS:
     cc /INCLUDE=CERN_ROOT:[INC] chbook-example.c
     link/exe=CHBOOK-EXAMPLE CHBOOK-EXAMPLE.obj,cern_root:[lib]packlib/lib,mathlib/lib,kernlib/lib
     RUN CHBOOK-EXAMPLE
    
     

If you prefer to use the gnu C compiler gcc, you could link using gcc and adding the FORTRAN specific libraries after the CERN libraries. The names of these libraries are different on all systems:

  1. HP:
     -lcl -lisamstub
     Example: gcc chbook-example.o `cernlib packlib,mathlib` -lcl -lisamstub -o chbook-example
     

VISUAL C++ compiler and MINUIT

This section shows a MINUIT example using cfortran.h on windows machines with Visual C++. To run them as C++ applications, the ".cpp" versions above must be used, and in addition, the output might need to be forced to get round linking incompatibilities in some versions of the Compaq Fortran and Visual C++ libraries. One way to procede to run this example is as follows:

  1. Create a folder C:\cern with all the *.lib from the CERN program library, and the *.h from cfortran.h.

  2. Create a folder C:\cern\minuit_test in which will be created a Visual C++ project from the 2 files listed below.

  3. Define the settings in Visual C++. In Project/Settings...:

    1. In C/C++ choose the category Preprocessor and add VISUAL_CPLUSPLUS.

      in Additional include directories put C:\cern

    2. In Link choose the category Input add packlib.lib in front of the list of libraries in Objects/library_modules.

      In Ignore libraries put libcd.lib.

      In Additional library path put C:\cern.

file minuit-main.c:

 /*
  * This example demonstrate how to call MINUIT from C.
  *
  * For question/problems contact: Heplib.Support@cern.ch
  *
  *
  * Authors: William Hanlon <whanlon@cosmic.utah.edu>,
  *          Gunter Folger <Gunter.Folger@cern.ch>
  */

 #include "cfortran.h"
 #include "minuit.h"
 #define Ncont 20

 int main()
 {
    int error_flag=0;
    PROTOCCALLSFSUB0(FCN,fcn)
    struct {
       double x[Ncont];
       double y[Ncont];
       int n;
    } pts;
    double f_null=0.;

    MNINIT(5,6,7);   /*  initialise  */
    MNSETI(" Minuit Example ");   /* set title */
    MNPARM(1,"X",0.,.1,f_null,f_null,error_flag);
    MNPARM(2,"-Y-",0.,.01,f_null,f_null,error_flag);
    MNEXCM(C_FUNCTION(FCN,fcn),"MIGRAD",0,0,error_flag,0);
    MNEXCM(C_FUNCTION(FCN,fcn),"MINOS",0,0,error_flag,0);
    MNCONT(C_FUNCTION(FCN,fcn),1,2,Ncont,pts.x[0],pts.y[0],pts.n, 0);
 }
 

file minuit-fcn.c:

 #include <math.h>
 #include <string.h>
 #include <cfortran.h>

 /* Authors: William Hanlon <whanlon@cosmic.utah.edu>,
  *          Gunter Folger <Gunter.Folger@cern.ch>
  */

 /* prototype for benefit of the wrapper */
 void fcn(int npar, double grad[3], double * fcnval,
          double xval[2],int iflag, void (*Dummy)());

 /* this macro creates a wrapper function called fcn_, which in turn calls the
  * function fcn defined below. The wrapper properly passes ints by value to
  * fcn, while it receives ints by reference from the fortran calling routine.
  */

 FCALLSCSUB6(fcn,FCN,fcn,INT,DOUBLEV,PDOUBLE,DOUBLEV,INT,ROUTINE)

 void fcn(int npar, double grad[3], double * fcnval,
          double xval[2],int iflag, void (*Dummy)())
 {
    double Xc=1.11,Yc=3.14;

    switch(iflag) {
       case 1:
 /*
  *      Initialise.
  */
          printf(" fcn_c called to initialise\n");
          break;
       case 2:
 /*
  *        derivatives...
  */
       break;

       default:
          *fcnval = pow(xval[0]-Xc,2.) + pow((xval[1]-Yc),3.)*xval[1];
          break;
    }
 }
 

CERN Program Library