Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 6/24/2024
Public
Document Table of Contents

BIND(C)

The BIND statement specifies that an object is interoperable with C and has external linkage. The syntax is:

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

C is the only language name that 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 lets you use a different external name than the one the standard prescribes. The companion C processor does this 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 the same decoration the C processor provides. NAME= is not a strict replacement for the ALIAS attribute extension. This extension 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) in Procedures

BIND(C) is often used in procedures. It can be used in INTERFACE blocks to specify the interface of an external interoperable procedure, and in any Fortran procedures that you want to make interoperable. For SUBROUTINE and FUNCTION, 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 example 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).

Note that the Fortran Standard prohibits an argument to a procedure with the BIND attribute to have both the VALUE and the OPTIONAL attributes.

The Fortran 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 need to provide the length another way - usually by appending C_NULL_CHAR to the end of a Fortran character entity. C_NULL_CHAR is defined in the intrinsic module ISO_C_BINDING.

However, you can also pass Fortran character variables to C strings (null terminated) by using the F_C_STRING function from the intrinsic module ISO_C_BINDING. The function has a character argument with kind C_CHAR. An optional second argument of type logical determines if any trailing blanks in the string should be stripped before inserting a null terminator. For example:

SUBROUTINE interop_sub () BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
CHARACTER(LEN=6) :: string
string = "abc"   
CALL c_func (F_C_STRING (string))
CALL c_func (F_C_STRING (string, .TRUE.)

The first call to c_func passes the value "abc " // C_NULL_CHAR. The second call to c_func passes the value "abc"// C_NULL_CHAR.

C pointers to contiguous arrays of single characters or pointers to strings can be converted to a scalar Fortran character pointer by using the C_F_STRPOINTER subroutine from the intrinsic module ISO_C_BINDING. For example:

SUBROUTINE interop_sub (c_sptr, c_char_arr) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_PTR)    :: c_sptr
CHARACTER(C_CHAR),DIMENSION(10),TARGET  :: c_char_arr
CHARACTER(LEN=:, C_CHAR),POINTER        :: f_sptr1, f_sptr2
CALL C_F_STRPOINTER (c_sptr, f_sptr1, 100)
CALL C_F_STRPOINTER (c_char_arr, f_sptr2)

In the above example, if c_sptr is associated with the literal string "ABCDEF", after the first call to C_F_STRPOINTER, f_sptr1(1:1) is 'A', and LEN(f_sptr1) is 6. If c_char_arr associated with a 10 element character array digits, where 'digits[0] = '0', … digits[9] = '9’, then after the second call to C_F_STRPOINTER, f_sptr2(1:1) is '0', and LEN(f_sptr2) is 10.