mixing fortran and c

Alan P. Barrett barrett at Daisy.EE.UND.AC.ZA
Mon Feb 18 22:07:28 AEST 1991


In article <2952 at charon.cwi.nl>,
dik at cwi.nl (Dik T. Winter) writes:
> In article <160 at mailgzrz.tu-berlin.de>
> duns1222 at w203zrz.zrz.tu-berlin.de (Martin Dunschen) writes:
>  > Hi all you high experienced C/FORTRAN programmers !
>  [...]
>  > But the last remaining thing is:
>  >       HOW TO PASS STRINGS ?
>  > 
> The answer can range from simple to impossible.

Here are the four methods I have seen:

a) A string passed from a Fortran routine to a C routine appears to the
   C routine as if it were a struct.  This struct contains the string
   length and a pointer to the actual characters, and possibly some
   other stuff as well.

b) Like (a), but a pointer to the struct is passed.

c) A string passed from a Fortran routine to a C routine appears to the
   C routine as if it were two consecutive arguments:  a pointer to the
   data followed by an integer length.  (This might actually be
   indistinguishable from method (a) on some systems.)

d) Like (c), but all the Fortran string length arguments are collected
   at the end of the argument list, after all the other arguments.

To clarify what I mean, here is an example.

If you have a Fortran routine that wants to call a subroutine
declared like this:

    SUBROUTINE SUBR (I, C1, J, C2)
    INTEGER I, J
    CHARACTER *(*) C1, C2

then the subroutine can possibly be replaced by a C routine like one of
these:

    /* method (a) */
    void subr (int i, struct ftnstring c1, int j, struct ftnstring c2);

    /* method (b) */
    void subr (int i, struct ftnstring *c1, int j, struct ftnstring *c2);

    /* method (c) */
    void subr (int i, char* c1data, int c1length, int j, char* c2data,
		int c2length);

    /* method (d) */
    void subr (int i, char* c1data, int j, char* c2data, int c1length,
		int c2length);


I am appending some sample code that I have used to convert between C
and Fortran strings.

ftntypes.h declares how the Fortran system represents strings.  Find out
how your system does it, and edit this file appropriately.

ftnstring.c contains the fstringtoc() and cstringtof() functions, which
do low level conversion between the two string types, truncating or
blank-padding as necessary.  These are intended to be called from a C
routine which is in turn called from Fortran.

ftngetterm.c contains a Fortran-callable function to get the name of the
terminal from which the program was invoked.

--apb
Alan Barrett, Dept. of Electronic Eng., Univ. of Natal, Durban, South Africa
Internet: barrett at ee.und.ac.za (or %ee.und.ac.za at saqqara.cis.ohio-state.edu)
UUCP: m2xenix!quagga!undeed!barrett    PSI-Mail: PSI%(6550)13601353::BARRETT

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Alan P Barrett <barrett at undeed> on Mon Feb 18 12:48:09 1991
#
# This archive contains:
#	ftntypes.h	ftnstring.c	ftngetterm.c	
#

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

echo x - ftntypes.h
cat >ftntypes.h <<'@EOF'
/* @(#)ftntypes.h 1.5 90/02/01 */
/* ftntypes.h
 * A.P. Barrett
 * defines types for C/Fortran interface
 */

/********* FORTRAN character variables ********/

/* Define preprocessor symbol F_CHR_STRUCT or F_CHR_STRUCTP if Fortran passes
 * each character arg as an item of type "ftn_character".  Use F_CHR_STRUCT
 * if this item is in fact a structure, or F_CHR_STRUCTP if the item is
 * a pointer to a structure.
 *
 * Define F_CHR_LENARG or F_CHR_LENARG_END if Fortran passes two arguments,
 * a char pointer and an integer length, for each character string.  Use
 * F_CHR_LENARG if the lengths are intermixed with the string pointers, or
 * F_CHR_LENARG_END if all the lengths are grouped together at the end of the
 * argument list.
 */

#if defined(hp9000s300)
#  define F_CHR_LENARG_END
#endif
#if defined(hp9000s500)
#  define F_CHR_STRUCT
#endif
#if defined(hp9000s800)
#  define F_CHR_LENARG /* could use F_CHR_STRUCT instead ??? */
#endif

/* If Fortran passes a structure (or pointer to a structure) define it here.
 * Structure members length and start must be the length and address of the
 * string.
 */

#if defined(F_CHR_STRUCT) || defined(F_CHR_STRUCTP)
	typedef struct {
#  if defined(hp9000s500)
		long junk1,junk2,junk3;	/* I don't know what this is */
		long length;	/* length of string */
		char *start;	/* pointer to start of actual data */
#  endif
#  if defined(hp9000s800)
		int length;	/* length of string */
		char *start;	/* pointer to start of actual data */
#  endif
	}
#  if defined(F_CHR_STRUCT)
	    ftn_character;
#  else /* F_CHR_STRUCTP */
	    * ftn_character;
#  endif
#endif

/********** FORTRAN logical variables *************/

typedef long ftn_logical;
#define ftn_TRUE	((ftn_logical)~0)  /* any non-zero value will do */
#define ftn_FALSE	((ftn_logical)0)

/********** FORTRAN integer, real, doubleprecision, complex *************/

typedef long ftn_integer;
typedef float ftn_real;
typedef double ftn_doubleprecision;
typedef struct {
	ftn_real  re,im; /* real and imaginary parts */
	} ftn_complex;
@EOF

chmod 444 ftntypes.h

echo x - ftnstring.c
cat >ftnstring.c <<'@EOF'
/* ftnstring.c
 * A P Barrett, 1986
 * conversions between fortran and C strings
 *
 * fstringtoc (fstring_start, fstring_length, cstring, cstring_length)
 *     converts a Fortran string to a C string, and returns a pointer to the
 *     C string.  The C string is truncated if fstring_length is larger then
 *     cstring_length-1.
 *
 * cstringtof (cstring, fstring_start, fstring_length)
 *     converts a C string to a Fortran string, and returns the length of the
 *     Fortran string, excluding additional trailing blanks.  The Fortran
 *     string is truncated or blank filled as appropriate.
 */

char *fstringtoc (fstring_start, fstring_length, cstring, cstring_length)
char *fstring_start;
int fstring_length;
char *cstring;
int cstring_length;
{
  int i;

  /* first copy the contents of the fortran string */
  for ( i=0 ; i<fstring_length && i <cstring_length ; i++ )
  {
    *(cstring+i) = *(fstring_start+i);
  }
  /* now put a '\0' at the end */
  *(cstring+i) = '\0';
  /* and return the result */
  return (cstring);
}


int cstringtof (cstring, fstring_start, fstring_length)
char *cstring;
char *fstring_start;
int fstring_length;
{
  int i;
  char ch;
  int length;

  /* copy characters until end of fortran string or null seen */
  for ( i=0 ; (i<fstring_length) && ((ch= *(cstring+i))!='\0') ; i++ )
  {
    *(fstring_start+i) = ch;
  }
  length = i;

  /* blank fill the fortran string if necessary */
  for ( ; i<fstring_length ; i++)
  {
    *(fstring_start+i) = ' ';
  }

  return (length);
}
@EOF

chmod 444 ftnstring.c

echo x - ftngetterm.c
cat >ftngetterm.c <<'@EOF'
/* ftngetterm.c
 * A P Barrett, 1987
 * return term name to a fortran prog
 */

#include "ftntypes.h"

int cstringtof(); /* convert char array to fortran string */

char *ttyname(); /* get terminal name */
int isatty();

/* this function returns the terminal name in a fortran
 * character variable.
 * call from fortran:
 *	character*(*) termname
 *      integer length
 *	length = gettermname (termname)
 */
#ifdef F_CHR_STRUCT
  int gettermname (termname)
  ftn_character termname;
#  define termname_start termname.start
#  define termname_length termname.length
#endif
#ifdef F_CHR_STRUCTP
  int gettermname (termname)
  ftn_character termname;
#  define termname_start termname->start
#  define termname_length termname->length
#endif
#ifdef F_CHR_LENARG
  int gettermname (termname_start,termname_length)
  char *termname_start;
  int termname_length;
#endif
#ifdef F_CHR_LENARG_END
  int gettermname (termname_start,termname_length)
  char *termname_start;
  int termname_length;
#endif
{
  int length;
  char *name;
  int num;

  /* if any of stderr, stdin or stdout is a terminal, get its name */
  if (isatty(num=2) || isatty(num=0) || isatty(num=1)) {
    name = ttyname(num);
  }
  else {
    name = "??";
  }

  length = cstringtof ( name, termname_start, termname_length );
  return (length);
}
@EOF

chmod 444 ftngetterm.c

exit 0



More information about the Comp.lang.c mailing list