The following table shows the data types available in the XL Fortran, Pascal, and C languages.
Figure 30. Corresponding Data Types in Fortran, C, and Pascal
When calling Fortran, the C and Pascal routines must pass arguments as pointers to the types listed in this table. | ||
XL Fortran Data Types | IBM C Data Types | XL Pascal Data Types |
---|---|---|
INTEGER(1) BYTE | signed char | PACKED -128..127 |
INTEGER(2) | signed short | PACKED -32768..32767 |
INTEGER(4) | signed int | INTEGER |
INTEGER(8) | signed long long (see note 1) | -- |
REAL REAL(4) | float | SHORTREAL |
REAL(8) DOUBLE PRECISION | double | REAL |
REAL(16) | long double (see note 2) | -- |
COMPLEX COMPLEX(4) | structure of two floats | record of two SHORTREALs |
COMPLEX(8) DOUBLE COMPLEX | structure of two doubles | record of two REALs |
COMPLEX(16) | structure of two long doubles | -- |
LOGICAL(1) | unsigned char | PACKED 0..255 |
LOGICAL(2) | unsigned short | PACKED 0..65535 |
LOGICAL(4) | unsigned int | -- |
LOGICAL(8) | unsigned long long (see note 1) | -- |
CHARACTER | char | CHAR |
CHARACTER(n) | char[n] | PACKED ARRAY[1..n] OF CHAR |
Integer POINTER | void * | POINTER, or typed pointer such as @INTEGER (see note 3) |
Array | array | ARRAY |
Sequence-derived type | structure (with C -qalign=packed option) | PACKED RECORD |
Notes:
|
Notes:
Related Information: | One or more sample programs under the directory /usr/lpp/xlf/samples illustrate how to call from Fortran to C. |
To access a C data structure from within a Fortran program, or to access a common block from within a C program, follow these steps:
program cstruct struct mystuff { real(8) a,d double a; integer b,c int b,c; . double d; . }; common /mystuff/ a,b,c,d . main() { . end }
If you do not have a specific need for a named common block, you can create a sequence-derived type with the same one-to-one mapping as a C structure, and pass it as an argument to a C function. You must compile the C source file with -qalign=packed.
Common blocks that are declared THREADLOCAL are thread-specific data areas that are dynamically allocated by compiler-generated code. A static block is still reserved for a THREADLOCAL common block, but the compiler and the compiler's run-time environment use it for control information. If you need to share THREADLOCAL common blocks between Fortran and C procedures, your C source must be aware of the implementation of the THREADLOCAL common block. For more information on THREADLOCAL common blocks, see the "Directives" chapter in the XL Fortran for AIX Language Reference and Appendix A. Sample Fortran Programs.
One difficult aspect of interlanguage calls is passing character strings between languages. The difficulty is due to the following underlying differences in the way that different languages represent such entities:
Note: | To have the compiler automatically add the null character to certain character arguments, you can use the -qnullterm Option. |
If you are writing both parts of the mixed-language program, you can make the C routines deal with the extra Fortran length argument, or you can suppress this extra argument by passing the string using the %REF function. If you use %REF, which you typically would for pre-existing C routines, you need to indicate where the string ends by concatenating a null character to the end of each character string that is passed to a C routine:
! Initialize a character string to pass to C character*6 message1 /'Hello\0'/ ! Initialize a character string as usual, append the null later character*5 message2 /'world'/ ! Pass both strings to a C function that takes 2 (char *) arguments call cfunc(%ref(message1), %ref(message2 // '\0')) end
For compatibility with C language usage, you can encode the following
escape sequences in XL Fortran character strings:
Figure 31. Escape Sequences for Character Strings
Escape | Meaning |
---|---|
\b | Backspace |
\f | Form feed |
\n | Newline |
\t | Tab |
\0 | Null |
\' | Apostrophe (does not terminate a string) |
\" | Double quotation mark (does not terminate a string) |
\ \ | Backslash |
\x | x, where x is any other character (the backslash is ignored) |
If you do not want the backslash interpreted as an escape character within strings, you can compile with the -qnoescape option.
Fortran stores array elements in ascending storage units in column-major order. C and Pascal store array elements in row-major order. Fortran and Pascal array indexes start at 1, while C array indexes start at 0.
The following example shows how a two-dimensional array that is declared by
A(3,2) is stored in Fortran, C, and Pascal:
Figure 32. Corresponding Array Layouts for Fortran, C, and Pascal
The Fortran array reference A(X,Y,Z) can be expressed in C as a[Z-1][Y-1][X-1] and in Pascal as A[Z,Y,X]. Keep in mind that although C passes individual scalar array elements by value, it passes arrays by reference. | |||
Fortran Element Name | C Element Name | Pascal Element Name | |
---|---|---|---|
Lowest storage unit | A(1,1) | A[0][0] | A[1,1] |
A(2,1) | A[0][1] | A[1,2] | |
A(3,1) | A[1][0] | A[2,1] | |
A(1,2) | A[1][1] | A[2,2] | |
A(2,2) | A[2][0] | A[3,1] | |
Highest storage unit | A(3,2) | A[2][1] | A[3,2] |
To pass all or part of a Fortran array to another language, you can use Fortran 90/Fortran 95 array notation:
REAL, DIMENSION(4,8) :: A, B(10) ! Pass an entire 4 x 8 array CALL CFUNC( A ) ! Pass only the upper-left quadrant of the array CALL CFUNC( A(1:2,1:4) ) ! Pass an array consisting of every third element of A CALL CFUNC( A(1:4:3,1:8) ) ! Pass a 1-dimensional array consisting of elements 1, 2, and 4 of B CALL CFUNC( B( (/1,2,4/) ) )
Where necessary, the Fortran program constructs a temporary array and copies all the elements into contiguous storage. In all cases, the C routine needs to account for the column-major layout of the array.
Any array section or noncontiguous array is passed as the address of a contiguous temporary, unless an explicit interface exists where the corresponding dummy argument is declared as an assumed-shape array or a pointer. To avoid the creation of array descriptors (which are not supported for interlanguage calls) when calling non-Fortran procedures with array arguments, either do not give the non-Fortran procedures any explicit interface, or do not declare the corresponding dummy arguments as assumed-shape or pointers in the interface:
! This explicit interface must be changed before the C function ! can be called. INTERFACE FUNCTION CFUNC (ARRAY, PTR1, PTR2) INTEGER, DIMENSION (:) :: ARRAY ! Change this : to *. INTEGER, POINTER, DIMENSION (:) :: PTR1 ! Change this : to * ! and remove the POINTER ! attribute. REAL, POINTER :: PTR2 ! Remove this POINTER ! attribute or change to TARGET. END FUNCTION END INTERFACE
Integer POINTERs always represent the address of the pointee object, and must be passed by value:
CALL CFUNC(%VAL(INTPTR))Note that the FORTRAN 77 POINTER extension from XL Fortran Version 2 is now referred to as "integer POINTER" to distinguish it from the Fortran 90 meaning of POINTER.
Fortran 90 POINTERs can also be passed back and forth between languages, but only if there is no explicit interface for the called procedure, or if the argument in the explicit interface does not have a POINTER attribute or assumed-shape declarator. You can remove any POINTER attribute or change it to TARGET, and change any deferred-shape array declarator to be explicit-shape or assumed-size.
Because of XL Fortran's call-by-reference conventions, you must pass even scalar values from another language as the address of the value rather than the value itself. For example, a C function passing an integer value x to Fortran must pass &x. Also, a C function passing a pointer value p to Fortran so that Fortran can use it as an integer POINTER must declare it as void **p. A C array is an exception: you can pass it to Fortran without the & operator.
To call subprograms written in languages other than Fortran (for example, user-written C programs, or AIX operating system routines), the actual arguments may need to be passed by a method different from the default method used by Fortran. C routines, including those in system libraries such as libc.a, require you to pass arguments by value instead of by reference. (Although C passes individual scalar array elements by value, it passes arrays by reference.)
You can change the default passing method by using the %VAL and %REF built-in functions in the argument list of a CALL statement or function reference. You cannot use them in the argument lists of Fortran procedure references or with alternate return specifiers.
You can use this built-in function with actual arguments that are CHARACTER(1), BYTE, logical, integer, real, or complex expressions, or sequence-derived type. Objects of derived type cannot contain pointers, arrays, or character structure components whose lengths are greater than one byte.
You cannot use %VAL with actual arguments that are array entities, procedure names, or character expressions of length greater than one byte.
%VAL causes XL Fortran to pass the actual argument as 32-bit or 64-bit intermediate values.
In 32-bit Mode |
---|
If the actual argument is one of the following:
Byte-named constants and variables are passed as if they were INTEGER(1). If the actual argument is a CHARACTER(1), the compiler pads it on the left with zeros to a 32-bit value, regardless of whether you specified the -qctyplss compiler option. |
In 64-bit Mode |
---|
If the actual argument is one of the following:
Byte-named constants and variables are passed as if they were INTEGER(1). If the actual argument is a CHARACTER(1), the compiler pads it on the left with zeros to a 64-bit value, regardless of whether you specified the -qctyplss compiler option. |
If you specified the -qautodbl compiler option, any padded storage space is not passed, except for objects of derived type.
EXTERNAL FUNC COMPLEX XVAR IVARB=6 CALL RIGHT2(%REF(FUNC)) ! procedure name passed by reference CALL RIGHT3(%VAL(XVAR)) ! complex argument passed by value CALL TPROG(%VAL(IVARB)) ! integer argument passed by value END
You can now specify an explicit interface for non-Fortran procedures to avoid coding calls to %VAL and %REF in each argument list, as follows:
INTERFACE FUNCTION C_FUNC(%VAL(A),%VAL(B)) ! Now you can code "c_func(a,b)" INTEGER A,B ! instead of END FUNCTION C_FUNC ! "c_func(%val(a),%val(b))" END INTERFACE
XL Fortran does not support calling certain types of Fortran functions from non-Fortran procedures. If a Fortran function returns a pointer, array, or character of nonconstant length, do not call it from outside Fortran.
You can call such a function indirectly:
SUBROUTINE MAT2(A,B,C) ! You can call this subroutine from C and the ! result is stored in C. INTEGER, DIMENSION(10,10) :: A,B,C C = ARRAY_FUNC(A,B) ! But you could not call ARRAY_FUNC directly. END
When you pass an optional argument by reference, the address in the argument list is zero if the argument is not present.
When you pass an optional argument by value, the value is zero if the argument is not present. The compiler uses an extra register argument to differentiate that value from a regular zero value. If the register has the value 1, the optional argument is present; if it has the value 0, the optional argument is not present.
Related Information: | See Order of Arguments in Argument List. |
Currently, declaring arguments with the INTENT attribute does not change the linkage convention for a procedure. However, because this part of the convention is subject to change in the future, we recommend not calling from non-Fortran procedures into Fortran procedures that have INTENT(IN) arguments.
Run-time errors are hard to find, and many of them are caused by mismatched procedure interfaces or conflicting data definitions. Therefore, it is a good idea to find as many of these problems as possible at compile or link time. To store type information in the object file so that the linker can detect mismatches, use the -qextchk compiler option.