6 Converting Between FORTRAN and C Strings

 6.1 The CNF Functions
 6.2 Handling Byte Strings (HDS Locators)
 6.3 Using Dynamic FORTRAN Character Strings

6.1 The CNF Functions

FORTRAN stores CHARACTER strings as fixed-length strings filled with trailing blanks, whereas C stores them as a variable-length strings each terminated by the null character. Although C strings are of variable length, there must of course be enough space reserved to store the maximum length that the string ever reaches plus one more character for the trailing null.

To aid the programmer in converting between the two forms of character strings, a number of C functions are provided in the CNF library. These handle all aspects of converting between the two types of string and provide options such as creating temporary strings, including the trailing blanks in the C version of a string and only copying a maximum number of characters. The process of converting from FORTRAN to C strings is known as “importing” and from C to FORTRAN as “exporting”.

None of the functions are very complicated and some of them are just a tidier way of achieving what could be done with a few lines of C in the calling program. Consequently in a time critical application it may be appropriate to include the source of a CNF function in your code, rather than incur the overheads of a making a function call.

Full descriptions of the CNF functions are provided in Appendix G.

Here is an example of how to use them. This is the same as an example from the machine specific section of this document. The use of the F77 macros and the CNF functions have made the C code easier to write and completely portable to all Starlink systems.

Example 5 – Converting character arguments between FORTRAN and C.
FORTRAN program:
        PROGRAM STRING
        CHARACTER STR*20
  
        CALL GETSTR( STR )
        PRINT *,STR
  
        END

C function:
  #include "f77.h"
  
  F77_SUBROUTINE(getstr)( CHARACTER(fortchar) TRAIL(fortchar) )
  {
    GENPTR_CHARACTER(fortchar)           /* Generate pointer to fortchar */
  
    char  *string = "This is a string";  /* A string to be printed */
  
  /* Copy the string to the function argument */
    cnfExprt( string, fortchar, fortchar_length );
  }

Other examples in this document illustrate the use of CNF functions for importing strings and calling FORTRAN from C.

6.2 Handling Byte Strings (HDS Locators)

Sometimes FORTRAN CHARACTER variables are used to contain strings of bytes rather than normal, printable character strings – a particular case of this is HDS locators (see SUN/92). In this case, special characters, such as NULL, cease to have their normal meaning and this could confuse the standard CNF import and export functions. For this reason, functions cnfImpch and cnfExpch are provided. These functions just import and export a given number of characters.

6.3 Using Dynamic FORTRAN Character Strings

The DECLARE_CHARACTER macro used in an earlier example (2) assumes that the length of the required FORTRAN character string is a constant, known at compile time. This is not always the case – for example, the character argument to be passed to the FORTRAN subroutine may be derived from an argument of the calling C function as in the case of a C wrap-around for a FORTRAN subroutine. To cater for this situation, macros are provided which will allocate and free space for the FORTRAN character string at run time. They make use of the CNF functions cnfCref and cnfFreef.

The following example illustrates their use for both input and output of strings from a FORTRAN subroutine which takes a given string, modifies it and returns the result.

Example 6 – Dynamic CHARACTER Arguments.

C main program

  void strStrip( char *in, char *out, int maxout );
  
  main(){
  char in[20]="Hello  there  !";
  char out[20];
  
  printf( "Input string is: %s\n", in );
  strStrip( in, out, 20 );
  printf( "Output string is: %s.\n", out );
  }

C wrap-around for a FORTRAN subroutine
  /* strStrip - A C wrap-around for FORTRAN subroutine STR_STRIP */
  #include "f77.h"
  
  extern F77_SUBROUTINE(str_strip)
    ( CHARACTER(fin), CHARACTER(fout) TRAIL(fin) TRAIL(fout) );
  
  void strStrip( char *in, char *out, int maxout ){
    DECLARE_CHARACTER_DYN(fin);
    DECLARE_CHARACTER_DYN(fout);
  
    F77_CREATE_CHARACTER(fin,strlen(in));
    F77_CREATE_CHARACTER(fout,maxout-1);
  
    cnfExprt( in, fin, fin_length );
  
    F77_CALL(str_strip)
       ( CHARACTER_ARG(fin), CHARACTER_ARG(fout)
         TRAIL_ARG(fin) TRAIL_ARG(fout) );
  
    cnfImprt( fout, fout_length, out );
  
    F77_FREE_CHARACTER(fin);
    F77_FREE_CHARACTER(fout);
  }

which is a C wrapper for the FORTRAN subroutine:

        SUBROUTINE STR_STRIP( FIN, FOUT )
  * Remove multiple spaces from a string
        IMPLICIT NONE
        INTEGER I, J
        CHARACTER*(*) FIN
        CHARACTER*(*) FOUT
  
        FOUT = FIN(1:1)
        I = 2
        J = 1
  
        DOWHILE ( I .LE. LEN(FIN) )
           IF ( FIN(I:I) .NE. ’ ’ ) THEN
              J = J + 1
              FOUT(J:J) = FIN(I:I)
           ELSE IF ( FOUT(J:J) .NE. ’ ’ )
              J = J + 1
              FOUT(J:J) = FIN(I:I)
           END IF
  
           I = I + 1
  
        ENDDO
  
        END

Here, DECLARE_CHARACTER_DYN is used in place of DECLARE_CHARACTER. It declares pointers rather than allocating space for the FORTRAN character strings to be passed to the FORTRAN subroutine. A variable to hold the string length is also declared.

The F77_CREATE_CHARACTER expands to executable statements which allocate space and set the pointers and string length. The F77_FREE_CHARACTER macro expands to executable statements which free the previously allocated space.