# Compaq Fortran
User Manual for
Tru64 UNIX and
Linux Alpha Systems

Previous | Contents | Index

# Chapter 11
Procedure Data Interfaces and Mixed Language Programming

This chapter contains the following topics:

- Section 11.1,Compaq Fortran Procedures and Argument Passing
- Section 11.2, Using the cDEC$ ALIAS and cDEC$ ATTRIBUTES Directives
- Section 11.3, Calling Between Compaq Fortran and C

Note For information about calling between Compaq Fortran 77 and Compaq Fortran, see Section A.5.

# 11.1 Compaq Fortran Procedures and Argument Passing

The bounds of the main program are usually defined by using PROGRAM and END or END PROGRAM statements. Within the main program, you can define entities related to calling a function or subroutine, including modules and interface blocks.

A function or subroutine is considered a subprogram. A subprogram can accept one or more data values passed from the calling routine; the values are called arguments.

There are two types of arguments:

- Actual arguments are specified in the subprogram call.
- Dummy arguments are variables within the function or subroutine that receive the values (from the actual arguments).

The following methods define the interface between procedures:

- Declare and name a function with a FUNCTION statement and terminate the function definition with an END FUNCTION statement. Set the value of the data to be returned to the calling routine by using the function name as a variable in an assignment statement (or by specifying RESULT in a FUNCTION statement).
  Reference a function by using its name in an expression.
- Declare and name a subroutine with a SUBROUTINE statement and terminate the subroutine definition with an END SUBROUTINE statement. No value is returned by a subroutine.
  Reference a subroutine by using its name in a CALL statement (or use a defined assignment statement).
- For an external subprogram, depending on the type of arguments or function return values, you may need to declare an explicit interface to the arguments and function return value by using an interface block.
  Declare and name an interface block with an INTERFACE statement and terminate the interface block definition with an END INTERFACE statement. The interface body that appears between these two statements consists of function or subroutine specification statements.
- You can make data, specifications, definitions, procedure interfaces, or procedures globally available to the appropriate parts of your program by using a module (use association).
  Declare a module with a MODULE statement and terminate the module definition with an END MODULE statement. Include the definitions and other information contained within the module in appropriate parts of your program with a USE statement. A module can contain interface blocks, function and subroutine declarations, data declarations, and other information.

For More Information:

- On the Compaq Fortran language, including statement functions and defined assignment statements not described in this manual, see the Compaq Fortran Language Reference Manual.

## 11.1.1 Explicit and Implicit Interfaces

An explicit interface occurs when the properties of the subprogram interface are known within the scope of the function or subroutine reference. For example, the function reference or CALL statement occurs at a point where the function or subroutine definition is known through host or use association. Intrinsic procedures also have an explicit interface.

An implicit interface occurs when the properties of the subprogram interface are not known within the scope of the function or subroutine reference. In this case, the procedure data interface is unknown to the compiler. For example, external routines (EXTERNAL statement) that have not been defined in an interface block have an implicit interface.

In most cases, you can use a procedure interface block to make an implicit interface an explicit one. An explicit interface provides the following advantages over an implicit interface:

- It provides better compile-time argument checking and fewer run-time errors.
- In some cases, it provides faster run-time performance.
- It provides ease of locating problems in source files since the features help to make the interface self-documenting.
- It allows use of some language features that require an explicit interface, such as array function return values.
- When passing certain types of arguments between Compaq Fortran and non-Fortran languages, an explicit interface may be needed. For example, detailed information about an assumed-shape array argument can be obtained from a Compaq Fortran array descriptor. An array descriptor is generated when an appropriate explicit interface is used for certain types of array arguments.

For More Information:

- See Section 11.1.7,Compaq Fortran Array Descriptor Format.

## 11.1.2 Types of Compaq Fortran Subprograms

There are three major types of subprograms:

- A subprogram might be local to a single program unit (known only within its host). Since the subprogram definition and all its references are contained within the same program unit, it is called an internal subprogram.
  An internal subprogram has an explicit interface.
- A subprogram needed in multiple program units should be placed within a module. To create a module subprogram within a module, add a CONTAINS statement followed by the subprogram code. A module subprogram can also contain internal subprograms.
  A module subprogram has an explicit interface in those program units that reference the module with a USE statement (unless it is declared PRIVATE).
- External subprograms are needed in multiple program units but cannot be placed in a module. This makes their procedure interface unknown in the program unit in which the reference occurs. Examples of external subprograms include general-purpose library routines in standard libraries and subprograms written in other languages, like C or Ada.
  Unless an external subprogram has an associated interface block, it has an implicit interface. To provide an explicit interface for an external subprogram, create a procedure interface block (see Section 11.1.3).
  For subprograms with no explicit interface, declare the subprogram name as external. You can do this by using the EXTERNAL statement within the program unit where the external subprogram reference occurs. This allows the linker to resolve the reference.
  An external subprogram must not contain PUBLIC or PRIVATE statements.

## 11.1.3 Using Procedure Interface Blocks

Procedure interface blocks allow you to specify an explicit interface for a subprogram as well as define generic procedure names. This section limits discussion to those interface blocks used to provide an explicit subprogram interface. For complete information on interface blocks, see the Compaq Fortran Language Reference Manual.

The components of a procedure interface block follow:

- Begin a procedure interface block with an INTERFACE statement. Unless you are defining a generic procedure name, user-defined operator, or user-defined assignment, only the word INTERFACE is needed.
- To provide the interface body, copy the procedure specification statements from the actual subprogram, including:
  - The FUNCTION or SUBROUTINE statements.
  - The interface body. For a procedure interface block, this includes specification (declaration) statements for the dummy arguments and a function return value (omit data assignment, FORMAT, ENTRY, DATA, and related statements).
    The interface body can include USE statements to obtain definitions.
    In parallel HPF programs (TU*X ONLY), any DISTRIBUTE, ALIGN, and INHERIT (!HPF) directives for the dummy arguments must also be included.
  - The END FUNCTION or END SUBROUTINE statements.
- Terminate the interface block with an END INTERFACE statement.
- To make the procedure interface block available to multiple program units, you can do one of the following:
  - Place the procedure interface block in a module. Reference the module with a USE statement in each program unit that references the subprogram (use association).
  - Place the procedure interface block in each program unit that references the subprogram.

For an example of a module that contains a procedure interface block, see Section 1.3.

## 11.1.4 Passing Arguments and Function Return Values

Compaq Fortran on Tru64 UNIX and Linux systems uses the same argument-passing conventions as Compaq Fortran 77 on Compaq Tru64 UNIX systems for non-pointer scalar variables and explicit-shape and assumed-size arrays.

When calling Compaq Fortran subprograms, be aware that Compaq Fortran expects to receive arguments the same way it passes them.

The main points about argument passing and function return values are as follows:

- Arguments are generally passed by reference: the address of the argument is passed.
  Unless explicitly specified otherwise (such as with the cDEC$ ATTRIBUTES directive or the %VAL built-in function), an argument contains the address of the data being passed, not the data itself.
  Assumed-shape arrays and deferred-shape arrays are passed by array descriptor.
  Arguments omitted by adding an extra comma (,) are passed as a zero by immediate value. OPTIONAL arguments that are not passed are also handled this way.
- Function return data is usually passed by immediate value (function return contains a value). Certain types of data (such as array-valued functions) are passed by other means.
  The value being returned from a function call usually contains the actual data, not the address of the data.
- Character variables, explicit-shape character arrays, and assumed-size character arrays are passed as arguments by reference along with an extra argument, called a "hidden length" argument, that gets passed by value after all actual arguments.
  The hidden length is an integer value. If two character scalar variables are passed, the argument list contains two extra hidden length arguments that respectively contain the length of the passed character arguments. Dummy arguments for character data can use an assumed length. You can use the `-mixed_str_len_arg` option to place the hidden length directly after its corresponding character argument instead of sequentially at the end of the argument list. See Section 3.62.
  When passing character arguments to a C routine as strings, the character argument is not automatically null-terminated by the compiler. To null-terminate a string from Compaq Fortran, use the CHAR intrinsic function or the null character escape sequence (described in the Compaq Fortran Language Reference Manual).
- External names have a trailing underscore (_) appended to their name and are in lowercase. On Linux systems, if an external name has an underscore in it, then two underscores are appended. For example, `EXTERNAL foo_bar` becomes `EXTERNAL foo_bar__` .
  The Compaq Fortran compiler appends the underscore to any reference to an external procedure name, as well as Compaq Fortran procedure declarations in the object file. This is mostly a concern when the program uses routines in Compaq Fortran and C, as described in Section 11.3.2.

The arguments passed from a calling routine must match the dummy arguments declared in the called function or subroutine (or other procedure), as follows:

- Arguments are kept in the same position as they are specified by the user.
  The exception to same position placement is the use of argument keywords to associate dummy and actual arguments.
- Each corresponding argument or function return value must at least match in data type, kind, and rank, as follows:
  - The primary Compaq Fortran intrinsic data types are character, integer, logical, real, and complex.
    To convert data from one data type to another, use the appropriate intrinsic procedures described in the Compaq Fortran Language Reference Manual.
    Also, certain attributes of a data item may have to match. For example, if a dummy argument has the POINTER attribute, its corresponding actual argument must also have the POINTER attribute Section 11.1.6).
  - You can use the kind parameter to specify the length of each numeric intrinsic type, such as INTEGER (KIND=8). For character lengths, use the LEN specifier, perhaps with an assumed length for dummy character arguments (LEN=*).
  - The rank (as number of dimensions) of the actual argument is usually the same (or less than) the rank of the dummy argument, unless an assumed-size dummy array is used.
    When using an explicit interface, the rank of the actual argument must be the same as the rank of the dummy argument.
    For example, when passing a scalar actual argument to a scalar dummy argument (no more than one array element or a nonarray variable), the rank of both is 0.
    You can pass an actual array to a dummy array of the same rank or you can pass an array section. If you use an assumed-shape array, the extents of the dummy array argument are taken from the actual array argument.
    Other rules which apply to passing arrays and pointers are described in Section 11.1.5, Section 11.1.6, and the Compaq Fortran Language Reference Manual.
- The means by which the argument is passed and received (passing mechanism) must match.
  By default, Compaq Fortran arguments are passed by reference. (See Table 11-3 for information about passing arguments with the C property.)
  When calling functions or other routines that are intended to be called from another language (such as C), be aware that these languages may require data to be passed by other means, such as by value.
  Most Compaq Fortran function return values are passed by value. Certain types of data (such as array-valued functions) are passed by other means.
  In most cases, you can change the passing mechanism of actual arguments by using the following Compaq extensions:
  - cDEC$ ATTRIBUTES directive (see Section 11.2.2)
  - Built-in functions (see Section 11.1.8)
- To explicitly specify the procedure (argument or function return) interface, provide an explicit interface.
  You can use interface blocks and modules to specify INTENT and other attributes of arguments.

For More Information:

- On passing arguments, function return values, and the contents of registers on Compaq Tru64 UNIX systems, see the Compaq Tru64 UNIX Calling Standard for Alpha Systems.
- On intrinsic data types, see Chapter 9 and the Compaq Fortran Language Reference Manual.
- On intrinsic procedures and attributes available for array use, see the Compaq Fortran Language Reference Manual.
- On explicit interfaces and when they are required, see the Compaq Fortran Language Reference Manual.
- On a Compaq Fortran example program that uses an external subprogram and a module that contains a procedure interface block, see Example 1-3.

## 11.1.5 Passing Arrays as Arguments

Certain arguments or function return values require the use of an explicit interface, including assumed-shape dummy arguments, pointer dummy arguments, and function return values that are arrays. This is discussed in the Compaq Fortran Language Reference Manual.

When passing arrays as arguments, the rank and the extents (number of elements in a dimension) should agree, so the arrays have the same shape and are conformable. If you use an assumed-shape array, the rank is specified and extents of the dummy array argument are taken from the actual array argument.

If the rank and extent (shape) do not agree, the arrays are not conformable. The assignment of elements from the actual array to the noncomformable (assumed-size or explicit-shape) dummy array is done by using array element sequence association. Using array element sequence associations is discussed in the Compaq Fortran Language Reference Manual.

Certain combinations of actual and dummy array arguments are disallowed.

For More Information:

- On the types of arrays and passing array arguments, see the Compaq Fortran Language Reference Manual.
- On explicit interfaces and when they are required, see the Compaq Fortran Language Reference Manual.
- On array descriptors, see Section 11.1.7.

## 11.1.6 Passing Pointers as Arguments

Previous sections have discussed the case where the actual and dummy arguments have neither the POINTER attribute nor the TARGET attribute.

The argument passing rules of like type, kind, and rank (for conformable arrays) or array element sequence association (for noncomformable arrays) apply when:

- Both actual and dummy arguments have the POINTER attribute.
- Dummy arguments have the TARGET attribute.
- Both actual and dummy arguments have neither attribute.

You can specify an actual argument of type POINTER and a dummy argument of type POINTER. You must use an explicit interface that defines the dummy argument with the POINTER attribute in the code containing the actual argument. This ensures that the pointer is passed, rather than the array data itself.

However, if you specify an actual argument of type POINTER and do not specify an appropriate explicit interface (such as an interface block), it is passed as actual (target) data.

For More Information:

- On using pointers and pointer arguments, see the Compaq Fortran Language Reference Manual.

## 11.1.7 Compaq Fortran Array Descriptor Format

When using an explicit interface (by association or procedure interface block), Compaq Fortran will generate a descriptor for the following types of dummy argument data structures:

- Pointers to arrays (array pointers)
- Allocatable arrays
- Assumed-shape arrays

To allow calling between Compaq Fortran 77 and Compaq Fortran, certain data structure arguments also supported by Compaq Fortran 77 do not use a descriptor, even when an appropriate explicit interface is provided. For example, since explicit-shape and assumed-size arrays are supported by both Compaq Fortran 77 and Compaq Fortran, a descriptor is not used.

However, for cases where the called routine needs the information in the Compaq Fortran descriptor, declare the routine with an assumed-shape or pointer argument and an explicit interface.

The byte components of the Compaq Fortran descriptor follow:

- Byte 0 contains a count of the number of dimensions (rank).
- Byte 1 should always contain a 1.
- Byte 2 contains the data type of the result, as follows:
  - 1 for INTEGER (KIND=1)
  - 2 for INTEGER (KIND=2)
  - 3 for INTEGER (KIND=4)
  - 4 for INTEGER (KIND=8)
  - 5 for LOGICAL (KIND=1)
  - 6 for LOGICAL (KIND=2)
  - 7 for LOGICAL (KIND=4)
  - 8 for LOGICAL (KIND=8)
  - 9 for REAL (KIND=4)
  - 10 for REAL (KIND=8)
  - 11 for REAL (KIND=16)
  - 12 for COMPLEX (KIND=4) or COMPLEX*8
  - 13 for COMPLEX (KIND=8) or COMPLEX*16
  - 14 for CHARACTER
  - 15 for RECORD
  - 17 for COMPLEX (KIND=16) or COMPLEX*32
- Bytes 3 to 7 (inclusive) are reserved.
- Bytes 8 to 15 contain the element length for character data, in bytes.
- Bytes 16 to 23 contain the address of the first element of an array.
- Bytes 24 to 39 are reserved.
- The remaining bytes (40 to 207) contain information about each array dimension, as follows:
  - Bytes 40 to 63 contain dimension information for rank 1
  - Bytes 64 to 87 contain dimension information for rank 2
  - Bytes 88 to 111 contain dimension information for rank 3
  - Bytes 112 to 135 contain dimension information for rank 4
  - Bytes 136 to 159 contain dimension information for rank 5
  - Bytes 160 to 183 contain dimension information for rank 6
  - Bytes 184 to 207 contain dimension information for rank 7

Within the dimension information (24 bytes) for each rank:

- Bytes 0 to 7 contain the number of bytes between two successive elements in this dimension.
- Bytes 8 to 15 contain the upper bound.
- Bytes 16 to 23 contain the lower bound.

For example, consider the following declaration:

       integer,target :: a(10,10)
       integer,pointer :: p(:,:)
       p => a(9:1:-2,1:9:3)
       call f(p)
       .
       .
       .

The descriptor for actual argument p would contain the following values:

- Byte 0 contains 2 (number of dimensions).
- Byte 1 contains 1 (always).
- Byte 2 contains 3 (data type of the result is the default INTEGER size, usually INTEGER (KIND=4)).
- Bytes 3 to 15 are reserved.
- Bytes 16 to 23 contain the address of the first element.
- Bytes 24 to 39 are reserved.
- Bytes 40 to 63 contain dimension information for rank 1, as follows:
  - Bytes 40 to 47 contain --8 (distance between elements)
  - Bytes 48 to 55 contain 5 (upper bound)
  - Bytes 56 to 63 contain 1 (lower bound)
- Bytes 64 to 87 contain dimension information for rank 2, as follows:
  - Bytes 64 to 71 contain 120 (distance between elements)
  - Bytes 72 to 80 contain 3 (upper bound)
  - Bytes 81 to 87 contain 1 (lower bound)
- Byte 87 is the last byte.

## 11.1.8 Argument-Passing Mechanisms and Built-In Functions

When a Compaq Fortran program needs to call a routine written in a different language (or in some cases a Fortran subprogram), there may be a need to use a form other the Compaq Fortran default passing mechanisms. For example, numeric arguments may need to be passed by immediate value instead of by reference.

To change the Compaq Fortran default mechanisms with the Compaq Fortran built-in functions, use the following functions:

- To change how an argument is passed (default passing mechanism), use the %VAL or %REF built-in functions for specific arguments.
- To compute the address of a storage element as an integer value, use the %LOC built-in function in any arithmetic expression.

The %VAL or %REF functions can only be used as unparenthesized arguments in actual argument lists.

Instead of the Compaq Fortran built-in functions, you can use the cDEC$ ATTRIBUTES directive to change the Compaq Fortran default passing mechanisms for either an entire call or for individual arguments. (See Section 11.2.2).

### 11.1.8.1 Passing Addresses --- %LOC Function

The %LOC built-in function computes the address of a storage element as an INTEGER*8 (Alpha UNIX systems) value. You can then use this value in an arithmetic expression. It has the following form:

    %LOC(arg)

The %LOC function is particularly useful for non-Fortran procedures that may require argument data structures containing the addresses of storage elements. In such cases, the data structures should be declared volatile to protect them from possible optimizations.

For More Information:

- On optimization and declaring volatile data, see Section 5.8.3.
- On the VOLATILE attribute, see the Compaq Fortran Language Reference Manual.

### 11.1.8.2 Passing Arguments by Immediate Value --- %VAL Function

The %VAL function passes the argument list entry as a 64-bit immediate value on Compaq Tru64 UNIX and Linux systems. It has the following form:

    %VAL(arg)

The argument-list entry generated by the compiler is the value of the argument (arg). Because argument-list entries are eight bytes long, the argument value must be an INTEGER (including INTEGER*8), LOGICAL (including LOGICAL*8), or REAL (REAL*4 and REAL*8) constant, variable, array element, or expression.

If a COMPLEX (KIND=4) or COMPLEX (KIND=8) argument is passed by value, two REAL arguments (one contains the real part; the other the imaginary part) are passed by immediate value. If a COMPLEX parameter to a routine is specified as received by value (or given the C attribute), two REAL parameters are received and stored in the real and imaginary parts of the COMPLEX parameter specified. COMPLEX*32 arguments cannot be passed by value.

If the value is a byte, word, or longword, it is sign-extended to eight bytes.

To produce a zero-extended value rather than a sign-extended value, use the ZEXT intrinsic function (see the Compaq Fortran Language Reference Manual).

### 11.1.8.3 Passing Arguments by Reference --- %REF Function

The %REF function passes the argument by reference. It has the following form:

    %REF(arg)

The argument-list entry the compiler generates will contain the address of the argument, (arg). The argument value can be a record name, a procedure name, or a numeric or character expression, array, character array section, or array element. In Compaq Fortran, passing by reference is the default mechanism for numeric values, so the %REF call is usually not needed. Passing character arrays with %REF caused the hidden length to be omitted.

### 11.1.8.4 Examples of Argument Passing Built-in Functions

The following examples show the use of the argument list built-in functions:

- The first constant is passed by reference. The second constant is passed by immediate value:

      CALL SUB(2,%VAL(2))

- The first character variable is passed by address and hidden length. The second character variable is passed by reference (no hidden length):

      CHARACTER(LEN=10) A,B
      CALL SUB(A,%REF(B))

- Both arrays are passed by reference:

      INTEGER IARY(20), JARY(20)
      CALL SUB(IARY,JARY)

For an example of passing integer data by value (using %VAL) and by reference (default) to a C function, see Section 11.3.7.

# 11.2 Using the cDEC$ ALIAS and cDEC$ ATTRIBUTES Directives

This section provides reference information about the following directives:

- The cDEC$ ALIAS (or !DEC$ ALIAS or *DEC$ ALIAS) directive lets you specify a name for an external subprogram that differs from the name used by the calling subprogram.
- The cDEC$ ATTRIBUTES (or !DEC$ ATTRIBUTES or *DEC$ ATTRIBUTES) directive lets you specify the properties for external data objects and procedures. This includes using C language rules, specifying how an argument is passed (passing mechanism), and specifying an alias for an external routine.

## 11.2.1 cDEC$ ALIAS directive

Use the cDEC$ ALIAS directive to specify that the external name of an external subprogram is different from the name by which the calling procedure references it.

The syntax is:

    cDEC$ ALIAS internal-name, external-name

The `internal-name` is the name of the subprogram as used in the current program unit.

The `external-name` is either a quoted character constant (delimited by single quotation marks) or a symbolic name.

If `external-name` is a quoted character constant, the value of that constant is used as the external name for the specified internal name. The character constant is used as it appears, with no modifications for case or addition or removal of punctuation characters. The default for the Compaq Fortran compiler is to force the name into lowercase and append an underscore unless directed otherwise.

If `external-name` is a symbolic name, the symbolic name (in lowercase) is used as the external name for the specified internal name and an underscore is appended. Any other declaration of the specified symbolic name is ignored for the purposes of the ALIAS directive.

The Compaq Tru64 UNIX and Linux linker may have restrictions on what appears in an external name and whether external names are case-sensitive.

For example, assume the following program (free source form):

    PROGRAM ALIAS_EXAMPLE
    !DEC$ ALIAS ROUT1, 'ROUT1A'
    !DEC$ ALIAS ROUT2, 'routine2_'
    !DEC$ ALIAS ROUT3, rout3A
          CALL ROUT1
          CALL ROUT2
          CALL ROUT3
    END PROGRAM ALIAS_EXAMPLE

The three calls are to external routines named ROUT1A, routine2_, and rout3A. Because rout3A is not in quotation marks (character constant), a trailing underscore is added (Compaq Fortran adds a trailing underscore to external names on UNIX systems unless directed otherwise) and the letter `A` becomes a lowercase `a` . For details about adding underscores on Linux systems, see Section 11.3.2.

This feature can be useful when porting code in which different routine naming conventions are in use. By adding or removing the cDEC$ ALIAS directive, you can specify an alternate routine name without recoding the application.

You can also use the DECORATE option with the ALIAS option so the external name specified in ALIAS has prefix and postfix decorations performed on it that are associated with the calling mechanism that is in effect.

The cDEC$ ALIAS and cDEC$ ATTRIBUTES ALIAS directives are synonymous.

## 11.2.2 cDEC$ ATTRIBUTES Directive

Use the cDEC$ ATTRIBUTES directive to specify properties for data objects and procedures. These properties let you specify how data is passed and the rules for invoking procedures. The cDEC$ ATTRIBUTES directive is intended to simplify mixed-language calls with Compaq Fortran routines written in C or Assembler. The STDCALL keyword is synonymous with the C keyword on Compaq Tru64 UNIX and Linux systems.

The cDEC$ ATTRIBUTES directive takes the following form:

     cDEC$ ATTRIBUTES att [,att]... :: object [,object]...

In this form:

> ### c

> Is the letter or character (c, C, *, !) that introduces the directive (see the Compaq Fortran Language Reference Manual).

> ### att

> Is one of the keywords listed in the Compaq Fortran Language Reference Manual. For example, C, ALIAS, REFERENCE, or VALUE.

> ### object

> Is the name of a data object used as an argument or procedure. Only one object is allowed when using the C, STDCALL, or ALIAS properties.

> The Compaq Fortran Language Reference Manual shows valid combinations of properties with the various types of objects.

The ATTRIBUTES options C, STDCALL, REFERENCE, VALUE, and VARYING all affect the calling convention of routines.

By default, Fortran passes all data by reference (except the hidden length argument of strings, which is a special case). If the C or STDCALL option is used, the default changes to passing almost all data by value except arrays.

In addition to the calling-convention options C and STDCALL, you can also specify argument options, VALUE and REFERENCE, to pass arguments by value or by reference, regardless of the calling convention option. Arrays can only be passed by reference.

Table 11-1 summarizes the effect of the most common Fortran calling-convention directives.

Table 11-1 Calling Conventions for ATTRIBUTES Options
Arguments | Default | C or STDCALL | C or STDCALL with REFERENCE
--- | --- | --- | ---
Scalar | Reference | Value | Reference
Scalar [value] | Value | Value | Value
Scalar [reference] | Reference | Reference | Reference
String | Reference, Len: End | String (1:1) | Reference, Len: End
String [value] | Error | String(1:1) | String(1:1)
String [reference] | Reference, No Len | Reference: No Len | Reference: No Len
Array | Reference | Reference | Reference
Array [value] | Error | Error | Error
Array [reference] | Reference | Reference | Reference
Derived type | Reference | Value, size dependent | Reference
Derived type [value] | Value, size dependent | Value, size dependent | Value, size dependent
Derived type [reference] | Reference | Reference | Reference
F90 Pointer | Descriptor | Descriptor | Descriptor
F90 Pointer [value] | Error | Error | Error
F90 Pointer [reference] | Descriptor | Descriptor | Descriptor

The terms used in Table 11-1 mean the following:

Term | Description
--- | ---
[value] | Assigned to the VALUE property
[reference] | Assigned to the REFERENCE property
Value | The argument value is pushed on the stack. All values are padded to the next 8-byte boundary.
Reference | The 8-byte argument address is pushed on the stack.
Len: End | The length of the string is pushed (by value) on the stack after all of the other arguments.
No Len | The length of the string is not available to the called procedure.
String(1:1) | For string arguments, the first character is converted to INTEGER(KIND=8) as in ICHAR(string(1:1)) and pushed onto the stack by value.
Error | Produces a compiler error.
Descriptor | 8-byte address of the array descriptor.
Size dependent | Derived-type arguments specified by value are passed as follows: Arguments of 1 to 4 bytes are passed by value Arguments of 5 to 8 bytes are passed by value in two registers Arguments of more than 8 bytes provide value semantics by passing a temporary storage address by reference.

The properties are described in the following sections.

### 11.2.2.1 C Property

The C property provides a convenient way for code written in Compaq Fortran to interact with routines written in C.

When applied to a subprogram, the C property defines the subprogram as having a specific set of calling conventions.

Table 11-2 summarizes the differences between the calling conventions:

Table 11-2 C Property and External Names
Item | Fortran Default | C Property Specified
--- | --- | ---
Trailing underscore added to procedure names | Yes | No
Case of external subprogram names | Lowercase, unless the ALIAS property is specified | Lowercase, unless the ALIAS property is specified
Argument passing | See Table 11-3 | See Table 11-3

In addition to the case of external names and the trailing underscore, the C property affects how arguments are passed, as described in Table 11-3.

Table 11-3 C Property and Argument Passing
Argument Variable Type | Fortran Default | C Property Specified for Routine
--- | --- | ---
Scalar (includes derived types) | Passed by reference | Passed by value
Scalar, with VALUE specified | Passed by value | Passed by value
Scalar, with REFERENCE specified | Passed by reference | Passed by reference
String | Passed by reference with hidden length | String (1:1) padded to integer length
String, with VALUE specified | Error | String (1:1) padded to integer length
String, with REFERENCE specified | Passed by reference with no hidden length | Passed by reference with no hidden length
Arrays, including pointers to arrays | Always passed by reference or descriptor | Always passed by reference or descriptor

If C is specified for a subprogram, arguments (except for arrays and characters) are passed by value. Subprograms using standard Fortran 95/90 conventions pass arguments by reference.

Character arguments are passed as follows:

- By Fortran default, hidden lengths are put at the end of the argument list.
- If C is specified without REFERENCE for the arguments, the first character of the string is passed by value (padded with zeros out to INTEGER*8 length).
- If C is specified with REFERENCE for the argument (or if only REFERENCE is specified), the string is passed with no length.

When the C property is specified, the case of the external name (EXTERNAL statement) is forced to lowercase, even if `-names as_is` or `-names uppercase` was specified during compilation. To allow a mixed case or uppercase name when the C property is specified, specify the ALIAS property for the same subprogram or external name.

Example 11-1 shows the Compaq Fortran code that calls the C function `pnst` (no underscore) by using the cDEC$ ATTRIBUTES C directive and C language passing conventions.

Example 11-1 Calling C Functions and Passing Integer Arguments

    ! Using !DEC$ ATTRIBUTES to pass argument to C. File: pass_int_cdec.f90

    interface
       subroutine pnst(i)
         !DEC$ ATTRIBUTES C :: pnst
         integer i
       end subroutine
    end interface

      integer :: i
      i = 99
      call pnst(i)             ! pass by value
      print *,"99==",i
    end

Example 11-2 shows the C function called `pnst` (no underscore) that is called by the example program shown in Example 11-1.

Example 11-2 Calling C Functions and Passing Integer Arguments

    /* get integer by value from Fortran. File: pass_int_cdec_c.c */

    void pnst(int i) {
        printf("99==%d\n",i);
            i = 100;
    }

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

    % cc -c  pass_int_cdec_c.c
    % f90 -o pass_cdec pass_int_cdec.f90 pass_int_cdec_c.o
    % pass_cdec
    99==99
    99==          99

### 11.2.2.2 ALIAS Property

You can specify the ALIAS property as cDEC$ ALIAS or as cDEC$ ATTRIBUTES ALIAS; they are equivalent. The ALIAS property allows you to specify that the external name of an external subprogram is different from the name by which the calling procedure references it (see Section 11.2.1).

When both ALIAS and C properties are used for a subprogram or external (EXTERNAL statement) name, the ALIAS property takes precedence over the C property. This allows you to specify case-sensitive names (the C attribute sets them to lowercase).

### 11.2.2.3 REFERENCE and VALUE Properties

The following cDEC$ ATTRIBUTES properties specify how a dummy argument is to be passed:

- REFERENCE specifies a dummy argument's memory location is to be passed, not the argument's value.
- VALUE specifies a dummy argument's value is to be passed, not the argument's memory location.

When a complex (KIND=4 or KIND=8) argument is passed by value, two floating-point arguments (one containing the real part, the other containing the imaginary part) are passed by immediate value. Conversely, if a COMPLEX parameter to a routine is specified as received by value (or given the C attribute), two REAL parameters are received and stored in the real and imaginary parts of the COMPLEX parameter specified.

Character values, substrings, assumed-size arrays, and adjustable arrays cannot be passed by value; neither can REAL*16 and COMPLEX*32 data. When REFERENCE is specified for a character argument, the string is passed with no length.

VALUE is the default if the C property is specified in the subprogram definition.

Consider the following free-form example, which passes an integer by value:

    interface
      subroutine foo (a)
       !DEC$ ATTRIBUTES C :: foo
          integer a
      end subroutine foo
    end interface

This subroutine can be invoked from Compaq Fortran using the name foo (no underscore):

    integer i
    i = 1
    call foo(i)

    end program

This is the actual subroutine code:

    subroutine foo (i)
     !DEC$ ATTRIBUTES C :: foo
        integer i
        i = i + 1
        .
        .
    end subroutine foo

For More Information:

- On Compaq Fortran intrinsic data types, see Chapter 9.
- On the Compaq Fortran language, see the Compaq Fortran Language Reference Manual.
- On the C language, see your operating system documentation.
- On passing arguments, function return values, and the contents of registers on Compaq Tru64 UNIX systems, see the Compaq Tru64 UNIX Calling Standard for Alpha Systems.

### 11.2.2.4 EXTERN and VARYING Properties

The EXTERN property specifies that a variable is allocated in another source file. EXTERN can be used in global variable declarations, but it must not be applied to dummy arguments.

You must use EXTERN when accessing variables declared in other languages.

The VARYING directive allows a variable number of calling arguments. If VARYING is specified, the C property must also be specified.

When using the VARYING directive, either the first argument must be a number indicating how many arguments to process, or the last argument must be a special marker (such as -1) indicating it is the final argument. The sequence of the arguments, and types and kinds, must be compatible with the called procedure.

For More Information:

- See the Compaq Fortran Language Reference Manual.

# 11.3 Calling Between Compaq Fortran and C

Before creating a mixed-language program that contains procedures written in Compaq Fortran and C, you need to know how to:

- Compile and link the program
- Use the platform-specific conventions for procedure names on Compaq Tru64 UNIX systems
- Use equivalent data arguments passed between the two languages

On Linux Alpha systems, this section assumes the usage of the Compaq C compiler ( `ccc` command).

## 11.3.1 Compiling and Linking Files

Use the `f90` or `fort` command (and not the `cc` or `ccc` command) to:

- Compile and link Compaq Fortran source files
- Link Compaq Fortran object files
- Link C object files with Compaq Fortran source or object files

The `f90` and `fort` commands pass the appropriate libraries to `ld` , including the Compaq Fortran libraries and `libc` .

You can use the `cc` and `ccc` commands with the `-c` option to compile C source files into object files.

For example, the following `f90` command compiles and links the Compaq Fortran calling main program `ex1.f90` and the called C function `uopen_.c` :

    % f90 ex1.f90 uopen_.c

You can use the `cc` or, on Linux systems, the `ccc` command to compile the C program into an object file before the `f90` command:

    % cc -c uopen_.c
    % f90 ex1.f90 uopen_.o

The `cc` ( `ccc` ) and `f90` ( `fort` ) commands:

1. Apply `cpp` to the `uopen_.c` file (done by `cc` and `ccc` )
2. Compile `uopen_.c` into the object file `uopen_.o` (done by `cc` and `ccc` )
3. Compile `ex1.f90` into an object file (done by `f90` and `fort` )
4. Link both resulting object files to create the file `a.out` file (done by `ld` )

When a C program calls a Compaq Fortran subprogram, specify the `-nofor_main` option on the `f90` command line:

    % cc -c  cmain.c
    % f90 -nofor_main cmain.o fsub.f90

To view the preprocessor and compilers used and the libraries passed to `ld` , use the `f90` command `-v` option.

For More Information:

- On the interaction of the `f90` command with other components, including options passed to `cc` , see Section 2.2.
- On the commands used to compile a Compaq Fortran and C example program, see Section 11.3.8.

## 11.3.2 Procedures and External Names

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

- The `ld` linker only allows one main program. Declare either the Compaq Fortran or the C program, but not both, as the main program. When the C program is the main program, use the `-nofor_main` option on the `f90` command line (see Section 11.3.1).
  In Compaq Fortran, you can declare a main program:
  - With the PROGRAM and END PROGRAM statements
  - With an END statement
  To create a Compaq Fortran subprogram, declare the subprogram with such statements as FUNCTION and END FUNCTION or SUBROUTINE and END SUBROUTINE.
  In C, you need to use a `main()` declaration for a main program. To create a C function (subprogram), declare the appropriate function name and omit the `main()` declaration.
- When declaring external names in C that will be called by Compaq Fortran, use lowercase.
  Compaq Fortran makes external names lowercase by default, so you need to make the C function name definition and declarations with lowercase letters. Although Compaq Fortran is case-insensitive, the C compiler and `ld` linker both treat external names as case-sensitive.
- In Compaq Fortran, external names and corresponding declarations have a trailing underscore (_) appended to their name.
  Due to differences in the argument-passing mechanisms and the data types between C and Compaq Fortran, convention requires that a trailing underscore be appended to external names (including function declarations) in the C program. This avoids accidental calls across the two languages.
  The Compaq Fortran compiler, by default, appends the underscore to references to external procedure names as well as Compaq Fortran procedure declarations. Any problems with the naming convention are reported by the linker when it searches for external names in an object file.
  For a C program to call a Compaq Fortran subprogram, the calling C program routine must append an underscore (_) to the name of the Compaq Fortran function (or subroutine) (if using the Compaq Fortran defaults). For example, if a C program wants to call a Compaq Fortran function named `exponent` , the C source code must refer to it as `exponent_` .
  Similarly, for a Compaq Fortran program to call a C function, the C function must use lowercase letters and have a trailing underscore. By default, the Compaq Fortran compiler converts external names to lowercase and appends a trailing underscore character when calling C language routines from Compaq Fortran. For example, if a Compaq Fortran program calls a C function using the name `conarray` in the function reference, the C function needs to be declared as `conarray_` .
- You can consider using some of the Compaq Fortran facilities provided to simplify the Compaq Fortran and C language interface:
  - You can use the cDEC$ ALIAS and cDEC$ ATTRIBUTES directives to specify alternative names for routines and change default passing mechanisms (see Section 11.2).
  - You can consider using the `f90` option `-assume nounderscore` to prevent Compaq Fortran from appending an underscore to most external names (see Section 3.15).
  - Instead of directly calling Compaq Tru64 UNIX and Linux system and library routines, consider using the language interface "jacket" routines provided by Compaq Fortran (see Chapter 12).
  - To perform I/O not supported by the Compaq Fortran run-time system, you can open a file with a C function and then use Compaq Fortran I/O statements to perform I/O (see Section 7.9). Indicate the name of the C function with the OPEN statement USEROPEN specifier, which causes the OPEN statement to call the C function to open the file.
  - A C main program can obtain more control by calling the Compaq Fortran run-time initialization routine `for_rtl_init_` and related Compaq Fortran library routines. (See Section 12.2, 3f Routines.)

## 11.3.3 Invoking a C Function from Compaq Fortran

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

If a value will be returned, use a function reference:

C Function Declaration | Compaq Fortran 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 | Compaq Fortran Subroutine Invocation
--- | ---
`void calc_( argument-list) { ... } ;` | `EXTERNAL CALC ... CALL CALC( argument-list)`

## 11.3.4 Invoking a Compaq Fortran Function or Subroutine from C

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

If a value is returned, use a FUNCTION declaration:

Compaq Fortran 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:

Compaq Fortran Declaration | C Invocation
--- | ---
`SUBROUTINE CALC( argument-list) ... END SUBROUTINE CALC` | `extern void calc_( argument-list) calc_( argument-list); ...`

## 11.3.5 Equivalent Data Types for Function Return Values

Both C and Compaq Fortran pass most function return data by value, but equivalent data types must be used. Table 11-4 lists equivalent function declarations in Compaq Fortran and C. See Table 11-5 for a complete list of data declarations.

Table 11-4 Equivalent Function Declarations in C and Compaq Fortran
C Function Declaration | Compaq Fortran 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 Compaq Fortran 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.3.10).

The Compaq Fortran 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 Compaq Fortran function is equivalent to a C language routine with two extra initial arguments added by the Compaq Fortran compiler:

- Address of the result
- Length of the result

For More Information:

- On the language interface "jacket" routines provided by Compaq Fortran, see Chapter 12.
- On opening a file using a C USEROPEN function, see Section 7.9.
- On passing character arguments, see Section 11.3.8.
- On Compaq Fortran intrinsic data types, see Chapter 9.
- On the Compaq Fortran language, see the Compaq Fortran Language Reference Manual.

## 11.3.6 Argument Association and Equivalent Data Types

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

- Passing arguments by reference (address).
- Receiving arguments by reference (address).
- Compaq Tru64 UNIX convention of appending a trailing underscore to external names and passing character data by using an extra argument for the character length.
- Compaq Linux convention of appending two trailing underscores to external names.

### 11.3.6.1 Compaq Fortran Intrinsic Data Types

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

- The kind parameter, such as REAL (KIND=4). Intrinsic integer and logical kinds are 1, 2, 4, and 8. Intrinsic real and complex kinds are 4 (single-precision), 8 (double-precision), and 16.
- A default-length name without a kind parameter, such as REAL or INTEGER. Certain `f90` command options can change the default kind, as described in Section 3.53 (for INTEGER and LOGICAL declarations), Section 3.78 (for REAL and COMPLEX declarations), and Section 3.34 (for DOUBLE PRECISION declarations).
- The Compaq Fortran extension of appending a *n size specifier to the default-length name, such as INTEGER*8.
- For double-precision real or complex data, the word DOUBLE followed by the default-length name without a kind parameter (specifically DOUBLE PRECISION and DOUBLE COMPLEX).

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 Compaq Fortran 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 Compaq Fortran 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:

- On Compaq Fortran intrinsic data types, see Chapter 9.
- On passing character data (example program), see Section 11.3.8.

### 11.3.6.2 Equivalent Compaq Fortran 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 Compaq Fortran 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 Compaq Fortran 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 Compaq Fortran subprogram, all arguments must be passed by reference because this is what the Compaq Fortran 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-5 for Compaq Tru64 UNIX systems.

Table 11-5 Compaq Fortran and C Data Types
Compaq Fortran 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;
complex (kind=16) x | struct { long double dreal; long double dimag } x; 1
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 Compaq Fortran for integer, logical, and real variables (see Chapter 9), and use the size consistent with that used in the C routine.

Compaq Fortran 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 Compaq Fortran 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 Compaq Fortran 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 Compaq Fortran function declaration that returns character data:

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

The following C code invokes the Compaq Fortran 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 Compaq Fortran is not automatically null-terminated. To null-terminate a string from Compaq Fortran, use the CHAR intrinsic function (as shown in the previous example and described in the Compaq Fortran Language Reference Manual).

## 11.3.7 Example of Passing Integer Data to C Functions

Example 11-3 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-3 C Functions Called by a Compaq Fortran Program

    /* get integer by value from Fortran. File: pass_int_to_c.c */

    void hln_(int i) {
        printf("99==%d\n",i);
            i = 100;
    }

    /* get integer by reference from Fortran */

    void mgn_(int *i) {
        printf("99==%d\n",*i);
            *i = 101;
    }

Example 11-4 shows the Compaq Fortran (main program) code that calls the two C functions `mgn_` and `hln_` .

Example 11-4 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-3 and Example 11-4) 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.3.8 Example of Passing Character Data Between Compaq Fortran and C

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

The Compaq Fortran program is named `test_setenv.f` .

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

The Compaq Fortran 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-5 shows the Compaq Fortran program `test_setenv.f` .

Example 11-5 Compaq Fortran 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-6 shows the C program `fort_setenv.c` .

Example 11-6 C Interface Function Called by Compaq Fortran

    /*  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-6) sets the environment variable PRINTER to the value lps40 (passed as arguments from the Compaq Fortran calling program) by calling the `setenv` library routine with the overwrite flag set to 1.

The C function (shown in Example 11-6) 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 Compaq Fortran code in Example 11-5 calls the `setenv_` C function:

      ret=setenv(ename,evalue,overwrite)

This function invocation passes the following arguments to the C function `setenv_` :

Compaq Fortran 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 Compaq Fortran to C is passed by reference. When passing character data from Compaq Fortran to C, the following rules apply:

- The Compaq Fortran character argument is not automatically terminated by a null string. To null-terminate a string, use the CHAR intrinsic function (described in the Compaq Fortran Language Reference Manual).
- An additional (hidden) argument that contains the string length is passed by value.

The C function (in Example 11-6) is declared as `setenv_` and accepts the Compaq Fortran 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 Compaq Fortran 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

## 11.3.9 Example of Passing Complex Data to C Functions

Example 11-7 shows Compaq Fortran code that passes a COMPLEX (KIND=4) value (1.0,0.0) by immediate value to subroutine `foo` . To pass COMPLEX arguments by value, the compiler passes the real and imaginary parts of the argument as two REAL arguments by immediate value.

Example 11-7 Calling C Functions and Passing Complex Arguments

      ! Using !DEC$ATTRIBUTES to pass COMPLEX argument by value to F90 or C.
      ! File: cv_main.f90

      interface
         subroutine foo(cplx)
           !DEC$ATTRIBUTES C :: foo
              complex cplx
         end subroutine
      end interface

        complex(kind=4) c
        c = (1.0,0.0)
        call foo(c)             ! pass by value

      end

If subroutine `foo` were written in Compaq Fortran, it might look similar to the following example. In this version of subroutine `foo` , the COMPLEX parameter is received by immediate value. To accomplish this, the compiler accepts two REAL parameters by immediate value and stores them into the real and imaginary parts, respectively, of the COMPLEX parameter cplx.

      ! File: cv_sub.f90

         subroutine foo(cplx)
           !DEC$ATTRIBUTES C :: foo
           complex cplx

           print *, 'The value of the complex number is ', cplx

         end subroutine

If subroutine `foo` were written in C, it might look similar to the following example in which the complex number is explicitly specified as two arguments of type float:

      /* File: cv_sub.c */

      #include <stdio.h>

      typedef struct {float c1; float c2;} complex;

      void foo(complex c)
      {
          printf("The value of the complex number is (%f,%f)\n", c.c1, c.c2);
      }

The main routine (shown in Example 11-7) might be compiled and linked to the object file created by the compilation of the Compaq Fortran subroutine and then run as follows:

    % f90 -o cv cv_main.f90, cv_sub.f90
    % cv
    The value of the complex number is (1.000000,0.0000000E+00)

The main routine might also be compiled and linked to the object file created by the compilation of the C subroutine and then run as follows:

    % cc -c cv_sub.c
    % f90 -o cv2 cv_main.f90 cv_sub.f90
    % cv2
    The value of the complex number is (1.000000,0.000000)

## 11.3.10 Handling User-Defined Structures

User-defined derived types in Compaq Fortran and user-defined C structures can be passed as arguments if the following conditions are met:

- The elements of the structures use the same alignment conventions (same amount of padding bytes, if any). The default alignment for C structure members is natural alignment. You can use the `cc` `-member_alignment` option or pragma to alter that alignment.
  Derived-type data in Compaq Fortran is naturally aligned (the compiler adds needed padding bytes) unless you specify the `-align norecords` option (see Section 3.3).
- All elements of the structures are in the same order.
  Compaq Fortran orders elements of derived types sequentially. However, those writing standard-conforming programs should not rely on this sequential order because the standard allows elements to be in any order unless the SEQUENCE statement is specified.
- The respective elements of the structures have the same data type and length (kind), as described in Section 11.3.6.
- The structure must be passed by reference (address).

## 11.3.11 Handling Scalar Pointer Data

When Compaq Fortran passes scalar numeric data with the pointer attribute, how the scalar numeric data gets passed depends on whether or not an interface block is provided:

- If you do not provide an interface block to pass the actual pointer, Compaq Fortran dereferences the Compaq Fortran pointer and passes the actual data (the target of the pointer) by reference.
- If you do provide an interface block to pass the actual pointer, Compaq Fortran passes the Compaq Fortran pointer by reference.

When passing scalar numeric data without the pointer attribute, Compaq Fortran passes the actual data by reference. If the called C function declares the dummy argument for the passed data to be passed by a pointer, it accepts the actual data passed by reference (address) and handles it correctly.

Similarly, when passing scalar data from a C program to a Compaq Fortran subprogram, the C program can use pointers to pass numeric data by reference.

Example 11-8 shows a Compaq Fortran program that passes a scalar (nonarray) pointer to a C function. Variable x is a pointer to variable y.

The function call to `ifunc1_` uses a procedure interface block, whereas the function call to `ifunc2_` does not. Because `ifunc1_` uses a procedure interface block (explicit interface) and the argument is given the pointer attribute, the pointer is passed. Without an explicit interface `(ifunc2_)` , the target data is passed.

Example 11-8 Calling C Functions and Passing Pointer Arguments

    ! Pass scalar pointer argument to C. File: scalar_pointer.f90

    interface
      function ifunc1(a)
      integer, pointer :: a
      integer ifunc1
      end function
    end interface

    integer, pointer :: x
    integer, target :: y

    y = 88
    x => y
    print *,ifunc1(x)           ! interface block visible, so pass
                                ! pointer by reference. C expects "int **"

    print *,ifunc2(x)           ! no interface block visible, so pass
                                ! value of "x" by reference. C expects "int *"
    print *,y
    end

Example 11-9 shows the C function declarations that receive the Compaq Fortran pointer or target arguments from the example in Example 11-8.

Example 11-9 C Functions Receiving Pointer Arguments

    /* C functions Fortran pointers. File: scalar_pointer.c  */

    int ifunc1_(int **a) {
        printf("a=%d\n",**a);
        **a = 99;
        return 100;
        }

    int ifunc2_(int *a) {
        printf("a=%d\n",*a);
        *a = 77;
        return 101;
    }

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

    % cc -c  scalar_pointer.c
    % f90 -o scalar_pointer scalar_pointer.f90 scalar_pointer.o
    % scalar_pointer
    a=88
             100
    a=99
             101
              77

## 11.3.12 Handling Arrays

There are two major differences between the way the C and Compaq Fortran languages handle arrays:

- Compaq Fortran stores arrays with the leftmost subscript varying the fastest (column-major order). With C, the rightmost subscript varies the fastest (row-major order).
- Although the default for the lower bound of an array in Compaq Fortran is 1, you can specify an explicit lower bound of 0 (zero) or another value. With C the lower bound is 0.

Because of these two factors:

- When a C routine uses an array passed by a Compaq Fortran subprogram, the dimensions of the array and the subscripts must be interchanged and also adjusted for the lower bound of 0 instead of 1 (or a different value).
- When a Compaq Fortran program uses an array passed by a C routine, the dimensions of the array and the subscripts must be interchanged. You also need to adjust for the lower bound being 0 instead of 1, by specifying the lower bound for the Compaq Fortran array as 0.

Compaq Fortran orders arrays in column-major order. The following Compaq Fortran array declaration for a 2 by 3 array creates elements ordered as y(1,1), y(2,1), y(1,2), y(2,2), y(1,3), y(2,3):

    integer y(2,3)

The Compaq Fortran declaration for a 2 by 3 array can be modified as follows to have the lowest bound 0 and not 1, resulting in elements ordered as y(0,0), y(1,0), y(0,1), y(1,1), y(0,2), y(1,2):

    integer y(0:1,0:2)

The following C array declaration for a 3 by 2 array has elements in row-major order as z[0,0], z[0,1], z[1,0], z[1,1], z[2,0], z[2,1]:

    int z[3][2]

To use C and Compaq Fortran array data:

- Consider using a 0 (zero) as the lower bounds in the Compaq Fortran array declaration.
  You may need to have the Compaq Fortran declaration with a lower bound 0 (not 1) for maintenance with C arrays or because of algorithm requirements.
- Reverse the dimensions in one of the array declaration statements. For example, declare a Compaq Fortran array as 2 by 3 and the C array as 3 by 2. Similarly, when passing array row and column locations between C and Compaq Fortran reverse the dimension numbers (interchange the row and column numbers in a two-dimensional array).

When passing certain array arguments, if you use an explicit interface that specifies the dummy argument as an array with the POINTER attribute or an assumed-shape array, the argument is passed by array descriptor (see Section 11.1.7).

For information about performance when using multidimensional arrays, see Section 5.5.

Example 11-10 shows a C function declaration for function `expshape_` , which prints the passed explicit-shape array.

Example 11-10 C Function That Receives an Explicit-Shape Array

    /* Get explicit-shape arrays from Fortran  */

    void expshape_(int  x[3][2]) {
        int i,j;
      for (i=0;i<3;i++)
         for (j=0;j<2;j++) printf("x[%d][%d]=%d\n",i,j,x[i][j]);
    }

Example 11-11 shows a Compaq Fortran program that calls the C function `expshape_` (shown in Example 11-10).

Example 11-11 Compaq Fortran Program That Passes an Explicit-Shape Array

    ! Pass an explicit-shape array from Fortran to C.

    integer :: x(2,3)
    x = reshape( (/(i,i=1,6)/), (/2,3/) )

    call expshape(x)
    end

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

    % cc -c  exparray.c
    % f90 -o exparray exparray.f90 exparray.o
    % exparray
    x[0][0]=1
    x[0][1]=2
    x[1][0]=3
    x[1][1]=4
    x[2][0]=5
    x[2][1]=6

For information on the use of array arguments with Compaq Fortran, see Section 11.1.5.

## 11.3.13 Handling Common Blocks of Data

The following notes apply to handling common blocks of data between Compaq Fortran and C:

- In Compaq Fortran, you declare each common block with the COMMON statement. In C, you can use any global variable defined as a struct, but that global variable (an external name) must end with an underscore.
- Data types must match unless you desire implicit equivalencing. If so, you must adhere to the alignment restrictions for Compaq Fortran data types.
- If there are multiple routines that declare data with multiple COMMON statements and the common blocks are of unequal length, the largest of the sizes is used to allocate space.
- A blank common block has a name of `_BLNK__` .
- You should specify the same alignment characteristics in C and Compaq Fortran. The default alignment for C structure members is natural alignment. You can use the `cc` `-member_alignment` option or pragma to alter that alignment.
  To specify the alignment of common block data items, specify the `-align dcommons` or `-align commons` option when compiling Compaq Fortran procedures using the `f90` command or specify data declarations carefully (see Section 5.4).

The following examples show how C and Compaq Fortran code can access common blocks of data. The C code declares a global structure, calls the `f_calc_` Compaq Fortran function to set the values, and prints the values:

    struct S {int j; float k;}r_;
    main() {
    f_calc_();
    printf("%d %f\n", r_.j, r_.k);
    }

The Compaq Fortran function then sets the data values:

    subroutine f_calc()
    common /r/j,k
    real k
    integer j
    j = 356
    k = 5.9
    return
    end

The C program then prints the structure member values 356 and 5.9 set by the Compaq Fortran function.

The previous example applies to Compaq Tru64 UNIX systems. On Compaq Linux systems, the external names with one underscore would have two trailing underscores.

# 11.4 Calling Between Parallel HPF and Non-Parallel HPF Code

When calling between parallel HPF and non-parallel HPF code (TU*X ONLY), the `-hpf` and `-nohpf_main` compile-time options are required in certain cases and prohibited in other cases.

Previous | Next | Contents | Index