The C_EXTERNAL and STDCALL keywords give the Fortran programmer the ability to
call C/C++ routines, forcing the compiler to generate extra code to handle some
of the data conversions. C_EXTERNAL is used when the "cdecl" calling convention
is used by C/C++ (e.g. the Win16 Windows API). STDCALL is used when the
"stdcall" calling convention is used by C/C++ (e.g. the Win32 Windows API).
An example of a type requiring data conversion is the string data type. As we
have already noted, C/C++ strings are NULL terminated, whilst Fortran strings
are fixed length, padded with spaces. The C_EXTERNAL and STDCALL declarations
for a function inform the compiler that the function or subroutine is written
in C/C++ and is external to this program module. If the function uses a string
data type, code is planted to generate a C/C++ style string before entering the
C/C++ function. Code is also generated after the function call to convert the C
style string back into a Fortran string. This frees the C/C++ programmer from
the additional complexities of providing the conversion code. It also means
that a Fortran programmer can call a third party library without converting all
string references into C/C++ strings before calling an external routine.
The C_EXTERNAL declaration has the following form (for STDCALL, simply replace
C_EXTERNAL by STDCALL or refer to the ClearWin+ User's Guide).
C_EXTERNAL name ['alias'] [(desc , ...)] [:restype]
name is the name to be used to call the function in the Fortran program.
alias is the external name used for the routine (i.e. the name that is used in
the C/C++ source code). This appears in single quotes and is case-sensitive.
desc describes the arguments that the routine receives and/or returns.
restype identifies the routine as a function and describes the type of the object
returned; this may be any function type other than CHARACTER.
Some examples of valid C_EXTERNAL declarations are given below.
This describes an external C/C++ routine which accepts no arguments and returns
no result. The corresponding C/C++ declaration would be
extern "C" void SUB(void)
and the function would be called by the Fortran statement CALL SUB.
C_EXTERNAL WRITE 'WriteFile' : INTEGER*4
This describes a C/C++ routine called WriteFile which accepts no
arguments, but returns an integer result. The routine is called from a Fortran
program by the statements
RESULT = WRITE()
The C/C++ code could have the following form
Before continuing, we must first examine the possible forms of the desc parameter
and the restype part of the declaration in more detail.
The desc parameter allows the programmer to over ride the default linkage
of arguments. If you use these argument descriptors, the number of arguments in
each occurrence of a call must agree with the number of descriptors in the
routine definition. desc may be any one of: REF, VAL, STRING, INSTRING,
The VAL specifier may only be used for numeric and logical scalars. Instead of
pushing the address of the value onto the stack, the actual value is pushed.
This allows C/C++ functions to use its arguments as local variables. The REF
specifier may be used with any Fortran object. This forces the Fortran program
to push the address of the object onto the stack. This is the default action
but should be used as a matter of good programming practice to allow the
compiler to check for the correct usage of external functions. So we may
additionally have the following descriptions:
for the UNIX low-level write function. This is defined in C/C++ as
int write(int handle, void *buffer, int amount)
but it now looks to the Fortran program as if it was a Fortran function declared
FUNCTION UNIX_WRITE(HANDLE, BUFFER, BUFSIZ)
INTEGER(KIND=3)::HANDLE, BUFFER, BUFSIZ, UNIX_WRITE
The remaining three types, STRING, INSTRING, OUTSTRING, are a little more
complicated. All three are used to describe a string object. Each one forces
the compiler to do differing amounts of work before the function call is made.
As we have already seen from the discussion at the start of this section, the
compiler can be forced to convert strings from Fortran strings to C/C++ strings
and visa-versa. This is the default action and is equivalent to the STRING
descriptor. However this causes an unnecessary overhead if and argument is to
be used for either input to a function or output from a function but not both.
In this case the INSTRING and OUTSTRING maybe used. This saves the redundant
copy operation from taking place. It is also possible to restrict the length of
the temporary variable used to store the string which is actually used in the
function call. The default length of the string is the length of the CHARACTER
array or 256 bytes in the case of a CHARACTER(LEN=*) array. This is done by
specifying the length of the string in parentheses after the descriptor.
Further examples of the C_EXTERNAL are: