Previous | Contents | Index |
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:
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) |
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); ... |
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:
DIGITAL Fortran 90 follows the argument-passing rules described in Section 11.1.4. These rules include:
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:
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:
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] |
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:
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 |
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:
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 |