DIGITAL Fortran 90
User Manual for
DIGITAL UNIX Systems


Previous Contents Index

11.4.2 Procedures and External Names

When designing a program that will use DIGITAL Fortran 90 and C, be aware of the following general rules and available DIGITAL Fortran 90 capabilities:

11.4.3 Invoking a C Function from DIGITAL Fortran 90

You can use a function reference or a CALL statement to invoke a C function from a DIGITAL Fortran 90 main or subprogram.

If a value will be returned, use a function reference:
C Function Declaration DIGITAL Fortran 90 Function Invocation
data-type calc_( argument-list)
{
...
} ;
EXTERNAL CALC
data-type :: CALC, variable-name
...
variable-name=CALC( argument-list)
...

If no value is returned, use a void return value and a CALL statement:
C Function Declaration DIGITAL Fortran 90 Subroutine Invocation
void calc_( argument-list)
{
...
} ;
EXTERNAL CALC
...
CALL CALC( argument-list)

11.4.4 Invoking a DIGITAL Fortran 90 Function or Subroutine from C

A C main program or function can invoke a DIGITAL Fortran 90 function or subroutine by using a function prototype declaration and invocation.

If a value is returned, use a FUNCTION declaration:
DIGITAL Fortran 90 Declaration C Invocation
FUNCTION CALC( argument-list)
data-type :: CALC
...
END FUNCTION CALC
extern data-type calc_( argument-list)
data-type variable-name;
variable-name=calc_( argument-list);
...

If no value is returned, use a SUBROUTINE declaration and a void return value:
DIGITAL Fortran 90 Declaration C Invocation
SUBROUTINE CALC( argument-list)
...
END SUBROUTINE CALC
extern void calc_( argument-list)

calc_( argument-list);
...

11.4.5 Equivalent Data Types for Function Return Values

Both C and DIGITAL Fortran 90 pass most function return data by value, but equivalent data types must be used. The following table lists equivalent function declarations in DIGITAL Fortran 90 and C. See Table 11-4 for a complete list of data declarations.
C Function Declaration DIGITAL Fortran 90 Function Declaration
float rfort_() function rfort()
real (kind=4) :: rfort
double dfort_() function dfort()
real (kind=8) :: dfort
int ifort_() function ifort()
integer (kind=4) :: ifort

Because there are no corresponding data types in C, you should avoid calling DIGITAL Fortran 90 functions of type REAL (KIND=16), COMPLEX, and DOUBLE COMPLEX, unless for complex data you pass a struct of two float (or double ) C values (see Section 11.4.10).

The DIGITAL Fortran 90 LOGICAL data types contain a zero if the value is false and a --1 if the value is true, which works with C conditional and if statements.

A character-valued DIGITAL Fortran 90 function is equivalent to a C language routine with two extra initial arguments added by the DIGITAL Fortran 90 compiler:

For More Information:

11.4.6 Argument Association and Equivalent Data Types

DIGITAL Fortran 90 follows the argument-passing rules described in Section 11.1.4. These rules include:

11.4.6.1 DIGITAL Fortran 90 Intrinsic Data Types

DIGITAL Fortran 90 lets you specify the lengths of its intrinsic numeric data types with the following:

The following declarations of the integer An are equivalent (unless you specified the appropriate f90 command option to override the default integer size):


INTEGER (KIND=4) :: A1 
INTEGER (4)      :: A2 
INTEGER          :: A3 
INTEGER*4        :: A4 

Character data in DIGITAL Fortran 90 is passed and received by address, using an extra hidden-length argument to contain the string length. Dummy character arguments can use assumed-length syntax for accepting character data of varying length.

Consider the following DIGITAL Fortran 90 subroutine declaration:


   SUBROUTINE H (C) 
   CHARACTER(LEN=*) C 

The equivalent C function declaration is:


  void h_(char *c, int len); 

The Fortran subroutine can be called from C as follows:


  . 
  . 
  . 
  char *chars[15]; 
  h_(chars, 15); 

For More Information:

11.4.6.2 Equivalent DIGITAL Fortran 90 and C Data Types

The calling routine must pass the same number of arguments expected by the called routine. For each argument passed, the manner (mechanism) of passing the argument and the expected data type must match what is expected by the called routine. For instance, C usually passes data by value and DIGITAL Fortran 90 typically passes argument data by reference (address and, when appropriate, length).

You must determine the appropriate data types in each language that are compatible. When you call a C routine from a DIGITAL Fortran 90 main program, certain built-in functions may be useful to change the default passing mechanism, as discussed in Section 11.1.8.

If the calling routine cannot pass an argument to the called routine because of a language difference, you may need to rewrite the called routine. Another option is to create an interface jacket routine that handles the passing differences.

When a C program calls a DIGITAL Fortran 90 subprogram, all arguments must be passed by reference because this is what the DIGITAL Fortran 90 routine expects. To pass arguments by reference, the arguments must specify addresses rather than values. To pass constants or expressions, their contents must first be placed in variables; then the addresses of the variables are passed.

When you pass the address of the variable, the data types must correspond as shown in Table 11-4 for DIGITAL UNIX systems:

Table 11-4 DIGITAL Fortran 90 and C Data Types
DIGITAL Fortran 90 Data Declaration C Data Declaration
integer (kind=2) x short int x;
integer (kind=4) x int x;
integer (kind=8) x long int x; __int64 x;
logical x unsigned x;
real x float x;
double precision x double x;
real (kind=16) x None 1
complex (kind=4) x struct { float real; float imag } x;
complex (kind=8) x struct { double dreal; double dimag } x;
character (len=5) x char x[5]


1The equivalent C declaration is long double (may not support X_floating).

Be aware of the various sizes supported by DIGITAL Fortran 90 for integer, logical, and real variables (see Chapter 9), and use the size consistent with that used in the C routine.

DIGITAL Fortran 90 LOGICAL data types contain a zero if the value is false and a --1 if the value is true, which works with C language conditional and if statements.

When one of the arguments is character data, the DIGITAL Fortran 90 compiler passes the address of the character data as an argument and adds the length of the character string to the end of the argument list (see Section 11.1.4).

When a C program calls a DIGITAL Fortran 90 subprogram, the C program must explicitly specify these items in an argument list in the following order:

  1. For a character function, the address of the character function result and the length of the character function result
  2. For normal arguments, the addresses of arguments or functions
  3. The lengths of any character string arguments, specified as integer variables (passed in the same order as the arguments)

For example, consider the following DIGITAL Fortran 90 function declaration that returns character data:


character(len=8) function ch() 
  ch = 'ABCDEFG' //CHAR(0) 
  return 
end 

The following C code invokes the DIGITAL Fortran 90 function as ch_, explicitly passing the address and length of the character data arguments, as follows:


char s[8] 
ch_(&s[0],8); 

Any character string passed by DIGITAL Fortran 90 is not automatically null-terminated. To null-terminate a string from DIGITAL Fortran 90, use the CHAR intrinsic function (as shown in the previous example and described in the DIGITAL Fortran Language Reference Manual).

11.4.7 Example of Passing Integer Data to C Functions

Example 11-5 shows C code that declares the two functions hln_ and mgn_ . These functions display the arguments received. The C language function hln_ expects the argument by value, whereas mgn_ expects the argument by reference (address).

Example 11-5 C Functions Called by a DIGITAL Fortran 90 Program

/* get integer by value from Fortran 90. File: pass_int_to_c.c */ 
 
void hln_(int i) { 
    printf("99==%d\n",i); 
        i = 100; 
} 
 
/* get integer by reference from Fortran 90 */ 
 
void mgn_(int *i) { 
    printf("99==%d\n",*i); 
        *i = 101; 
} 

Example 11-6 shows the DIGITAL Fortran 90 (main program) code that calls the two C functions mgn_ and hln_ .

Example 11-6 Calling C Functions and Passing Integer Arguments

! Using %REF and %VAL to pass argument to C. File: pass_int_to_cfuncs.f90 
  integer :: i 
  i = 99 
  call hln(%VAL(i))     ! pass by value 
  print *,"99==",i 
 
  call mgn(%REF(i))     ! pass by reference - %REF is optional in this case 
  print *,"101==",i 
  i = 99 
  call mgn(i)           ! pass by reference 
  print *,"101==",i 

The files (shown in Example 11-5 and Example 11-6) might be compiled, linked, and run as follows:


% cc -c  pass_int_to_c.c
% f90 -o pass_int_to_c pass_int_to_cfuncs.f90 pass_int_to_c.o
% pass_int_to_c
99==99 
99==          99 
99==99 
101==         101 
99==99 
101==         101 

11.4.8 Example of Passing Character Data Between DIGITAL Fortran 90 and C

The following examples show a DIGITAL Fortran 90 program that calls a C function that serves as an interface (jacket) routine to the setenv library routine (described in setenv(3)).

The DIGITAL Fortran 90 program is named test_setenv.f .

The C program that contains the setenv_ interface function is named fort_setenv.c .

The DIGITAL Fortran 90 program performs the following tasks:

  1. Calls the getenv function (a Section 3f library routine) and displays the current value of the environment variable PRINTER (described in getenv(3f)
  2. Calls the setenv_ interface function to set the new value for the environment variable PRINTER
  3. Calls the getenv function again and displays the new value of the environment variable PRINTER

Example 11-7 shows the DIGITAL Fortran 90 program test_setenv.f .

Example 11-7 DIGITAL Fortran 90 Program Calling a C Function

!     test_setenv.f 
 
      character(len=50) :: ename, evalue 
      integer           :: overwrite, setenv, ret 
 
!     Use 3f routine getenv to return PRINTER environment variable value 
 
      call getenv('PRINTER',evalue) 
 
!     Now look at current value 
 
      write(6,*) 'Previous env. variable value of PRINTER is: ', evalue 
 
!     Use setenv C function. Overwrite flag = non-zero means 
!     overwrite any existing environment variable. 
! 
!     Returns -1 if there was an error in setting the environment variable 
 
      ename  = 'PRINTER' 
      evalue = 'lps40' 
      overwrite = 1 
      ret = setenv(ename,evalue,overwrite) 
 
      if (ret < 0) write (6,*) 'Error setting env. variable' 
      
!     Now look at current value 
      evalue = ' '                          
      call getenv('PRINTER',evalue) 
      write(6,*)  'New env. variable value of PRINTER is: ', evalue 
 
      end 

Example 11-8 shows the C program fort_setenv.c .

Example 11-8 C Interface Function Called by DIGITAL Fortran 90

/*  fort_setenv.c */ 
#include <stdlib.h> 
 
int setenv_(char *ename,char *evalue,int *overwrite,int ilen1,int ilen2) 
{ 
     int setenv(), lnblnk_(), i1, i2, ow, rc; 
     char *p1, *p2; 
 
     /* Get string length of each input parameter */ 
     i1 = lnblnk_(ename,ilen1); 
     i2 = lnblnk_(evalue,ilen2); 
 
     /* Allocate temporary storage */ 
     p1 = malloc((unsigned) i1+1); 
     if( p1 == NULL ) return(-1); 
     p2 = malloc((unsigned) i2+1); 
     if( p2 == NULL ) { 
        free(p1); 
        return(-1); 
     } 
 
     /* Copy strings, and NUL terminate */ 
     strncpy(p1,ename,i1); 
     p1[i1] = '\0'; 
     strncpy(p2,evalue,i2); 
     p2[i2] = '\0'; 
 
     ow = *overwrite; 
 
     /* Call the setenv library routine to set the environment variable */ 
 
     rc = setenv(p1, p2, ow); 
     free(p1); 
     free(p2); 
     return(rc); 
} 

The setenv_ function (shown in Example 11-8) sets the environment variable PRINTER to the value lps40 (passed as arguments from the DIGITAL Fortran 90 calling program) by calling the setenv library routine with the overwrite flag set to 1.

The C function (shown in Example 11-8) uses the passed length to find the last nonblank character and uses the string up to that character. The C variables ilen1 and ilen2 receive the hidden length of the character strings ename and evalue respectively. The C function allocates storage, including an extra byte for the null-terminator to each string. The extra byte is used as part of an argument when calling the setenv library routine.

The following DIGITAL Fortran 90 code in Example 11-7 calls the setenv_ C function:


  ret=setenv(ename,evalue,overwrite) 

This function invocation passes the following arguments to the C function setenv_ :
DIGITAL Fortran 90 Variable Purpose Data Type How Passed
ename Environment variable name character by reference, not null-terminated
evalue Environment variable string character by reference, not null-terminated
overwrite Overwrite flag for setenv integer by reference
not declared Hidden length of ename integer by value
not declared Hidden length of evalue integer by value

Data passed from DIGITAL Fortran 90 to C is passed by reference. When passing character data from DIGITAL Fortran 90 to C, the following rules apply:

The C function (in Example 11-8) is declared as setenv_ and accepts the DIGITAL Fortran 90 arguments with the following function declaration:


int setenv_(ename,evalue,overwrite,ilen1,ilen2) 
char *ename, *evalue; 
int  *overwrite; 
int  ilen1, ilen2; 

The status returned from the C function to the calling DIGITAL Fortran 90 program is an integer passed by value. (The C function obtains this value from setenv library routine.)

To create the executable program, the files might be compiled with the following commands:


% cc -c fort_setenv.c
% f90 test_setenv.f fort_setenv.o

When executed, a.out displays:


% a.out
 Previous env. variable value of PRINTER is:
  lpr
 New env. variable value of PRINTER is:
  lps40


Previous Next Contents Index