In Win32, Fortran by default passes a hidden length argument for strings. This argument is easily accessible to other languages, unlike the string-length information passed in 16-bit versions of Fortran. The hidden length argument consists of an unsigned 4-byte integer, always passed by value, immediately following the character string argument.
For example, if a Fortran program sets up the following call to a routine, Pass_Str
, implemented in C:
INTERFACE TO SUBROUTINE Pass_Str (string)
CHARACTER*(*) string
END
Then the C routine must expect two arguments:
void __stdcall PASS_STR (char *string, unsigned int length_arg )
Another important difference is in the format of the strings themselves. C strings are null-terminated. For example, given the following assignment:
Char *cstring="C text string";
The string data is stored as shown in the following figure.
Fortran strings are not null-terminated, and they are padded with blank spaces when assigned string data that is shorter than the declared length. For example, given the following assignment:
CHARACTER*14 forstring
DATA FORSTRING /"Fortran STRING'/
The string data is stored as follows. Note that if the string were any longer, it would be padded with trailing blanks.
A more efficient approach, wherever possible, is to adopt C string behavior. When the C or STDCALL attribute is applied to a routine, Fortran does not pass a hidden length argument. Furthermore, you can use the C-string feature to assign null-terminated string data in Fortran, as follows:
CHARACTER*20 forstring
DATA forstring /'This is a string'C/
The string variable, forstring
, can then be passed to a C routine. If the C or STDCALL attribute is used, Fortran passes forstring just as C does: pushing the address of a null-terminated string onto the stack, with no hidden length argument.
Note Fortran functions of type CHARACTER*(*) place a hidden string argument at the beginning of the parameter list; this may include both string address and length, as appropriate. C functions that implement such a call from Fortran must declare this hidden string argument explicitly and use it to return a value. However, you are more likely to avoid errors by not using character-string return types. Use subroutines whenever possible.
The following example demonstrates how a Fortran main program calls a C function that translates a string to all-uppercase. Because the string is passed by reference, there is no need to use a string return type. Note that the C attribute stops Fortran from passing a hidden string-length argument, and the DATA statement uses a “C” to specify null termination.
C File FORMAIN.FOR
C
INTERFACE TO SUBROUTINE Ucase [C,ALIAS:'_Ucase'] (text)
CHARACTER*(*) text [REFERENCE]
END
CHARACTER*40 forstring
DATA forstring /'This is a sample string.'C/
WRITE (*, *) forstring
CALL Ucase (forstring)
WRITE (*, *) forstring
END
/* File CSTR.C */
#include <ctype.h>
void Ucase( char *string )
{
char *ptr;
for (ptr = string; *ptr; ptr++)
*ptr = toupper( *ptr );
}
This use of C strings is usually the best approach, because most C library functions, as well as API functions, assume null-termination. However, if you use C to write string-manipulation functions, it is a good idea to translate null-terminated strings back into blank-padded strings after the C function returns. The following code performs this operation:
SUBROUTINE Fix_C_Str (text, length)
CHARACTER*(*) text
INTEGER*4 length
INTEGER*4 i
C Find the first null ('\0')
i = 1
DO WHILE ((i .LE. length) .AND. (text(i:i) .NE. '\0'))
i = i + 1
END DO
C Pad with blanks to the end of the string
DO WHILE (i .LE. length)
text (i:i) = ' '
END DO
END