BIND(C)

Fortran 2003 introduced the language-binding-spec attribute, using the keyword BIND. The syntax is:

BIND(C [, NAME=scalar-default-char-constant-expr])

C is the only language name you can specify. Generally, an entity with the BIND(C) attribute behaves as if it were the corresponding entity in the companion C processor.

The optional NAME= specifier allows you to use a different external name than the one the standard prescribes, which is what the companion C processor would do with the Fortran name forced to lowercase. If the C name was mixed-case, specify the mixed-case name here without any name decoration, such as leading underscores. The compiler applies whatever decoration the C processor would with the same name. So NAME= is not a strict replacement for the ALIAS attribute extension, it is more like ALIAS combined with DECORATE.

BIND(C) is not equivalent to ATTRIBUTES C. Although these both downcase the external name, BIND(C) does not imply pass-by-value and has other effects that are different from ATTRIBUTES C.

You can specify ATTRIBUTES STDCALL for an interoperable procedure (a procedure whose declaration includes the BIND(C) language binding attribute). This combination has the following effects for Windows* applications targeting IA-32 architecture:

  • The calling mechanism is changed to STDCALL, which affects how the stack is cleaned up on procedure exit.

  • The external name from the BIND attribute is suffixed with @n, where n is the number of bytes to be removed from the stack on return.

No other effects from STDCALL, such as pass-by-value, are provided. The Fortran standard VALUE attribute (not ATTRIBUTES VALUE) may be used if desired. For all other platforms, specifying STDCALL with BIND(C) has no effect. For more information, see ATTRIBUTES C and STDCALL.

BIND(C) on procedures

BIND(C) is often used on procedures. It can be specified in INTERFACE blocks to specify the interface of an external interoperable procedure, and on any Fortran procedures that you want to make interoperable. For SUBROUTINEs and FUNCTIONs, you need to specify BIND(C) after the argument list. For functions, you can specify BIND(C) before or after the RESULT clause. For example:

SUBROUTINE INTEROP_SUB (ARG) BIND(C,NAME="InteropSub")

FUNCTION INTEROP_FUN (ARG) BIND(C,NAME="InteropFun") RESULT (IAMFUN)

The above includes an external name, which is not required. You can also specify BIND(C) in a PROCEDURE declaration, in which case it appears in the normal list of attributes before the :: separator.

Specifying BIND(C) for procedures results in the following:

  • The external name is what the C compiler would use, with the Fortran name lowercased (unless NAME= is specified).

  • Arguments are passed and received by reference (unless the VALUE attribute is specified for the argument).

  • Only interoperable arguments are allowed.

  • No hidden arguments are allowed.

  • Function type must be interoperable and function values are returned exactly as the C compiler would (this mainly affects small derived types).

The standard allows for passing character strings to interoperable procedures. You can pass a character argument of default kind (kind C_CHAR is the default in Intel® Fortran); the corresponding dummy argument is an explicit-shape array of single characters. Because no length is passed, you will need to provide the length another way (usually by appending a NUL character on the end.)

The standard does not provide an easy way to write a Fortran interoperable routine that accepts a string from C. You must declare the dummy argument as an array of single characters. You can use the combination of the C_LOC and C_F_POINTER procedures, both defined in intrinsic module ISO_C_BINDING, to "cast" a character array argument to a Fortran pointer to a character string. An example follows:

subroutine Interop_sub(arg) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
CHARACTER, DIMENSION(*) :: ARG
CHARACTER(1000), POINTER :: LCL_ARG ! Local pointer to argument 
CALL C_F_POINTER(C_LOC(ARG), LCL_ARG)

In the above, ARG comes in as an assumed-size array of single characters, with no length. The C_F_POINTER subroutine converts a C pointer to a Fortran pointer. C_LOC is used to get a C pointer (of type C_PTR) of the argument and convert it to the Fortran pointer LCL_ARG. The result is that you can use LCL_ARG as a character string.

In the example, LCL_ARG has an explicit length. There is no way to make this pointer the correct length of the incoming string. Use INDEX to find the location of the NUL character, or some other method, to obtain the length and then use that in subsequent references.

For more complete information about compiler optimizations, see our Optimization Notice.