passing Fortran characters to C (was: VAX - passing strings between C and FORTRAN)
Alex Martelli
staff at cadlab.sublink.ORG
Fri Feb 8 21:10:54 AEST 1991
springer at khonshu.Colorado.EDU (Jann Springer) writes:
...
:To transfer a character string between C and Fortran involves
:using a descriptor, which is how Fortran passes character strings.
(explanation deleted)
:This explanation assumes you are using VMS and not Ultrix.
Here's a technique which works on VMS, Ultrix, several more Unixen, and
ALMOST on OS/2 and MSDOS (with some extra complications, omitted).
We have a header file, ftnintf.h, which has (simplified):
#if (identification of your choice for most f77-derived Fortran's)
# define __NEED_UNDERLINE 1
#endif
/* no underline for VMS, HP/UX, IBM RISC/6000, etc */
#if __NEED_UNDERLINE
# define FTN(x) _paste(x,_)
#else
# define FTN(x) x
#endif
typedef short I2; typedef long I4; typedef char *PTR;
#if VMSVAX
typedef struct { I2 len; I2 dum; PTR adr; } VAXCH;
# define DCA(x) x
# define DCL(x)
# define DCHAL(x) VAXCH*x
# define CHA(x) (x->adr)
# define LEN(x) ((I4)(x->len))
#else
# if HP800
# define DCA(x) x, _paste(L,x)
# define DCL(x)
# else
# define DCA(x) x
# define DCL(x) ,_paste(L,x)
# endif /* HP800 */
# ifdef APO
# define DCHAL(x) PTR x;I2* _paste(L,x)
# define LEN(x) ((I4)*_paste(L,x)
# else
# define DCHAL(x) PTR x;I4 _paste(L,x)
# define LEN(x) _paste(L,x)
# endif /* APO */
# define CHA(x) x
#endif
where APO identifies Apollo Domain/OS machines, HP800 is for HP
9000/800, VMSVAX for guess-what. _paste(a,b) is a macro to give ONE
token out of the two tokens a and b; this is obtained with a##b in ANSI
C, with a/**/b in common or garden C. There are further complications
for access to COMMON blocks, Microsoft compilers, procedures passed as
parameters, calling back from Fortran to C, and so on, but I'm going to
spare you these. Anyway the usage is then, say:
#include "ftnintf.h"
void
FTN(counteqs)(DCA(one), DCA(two), ires DCL(one) DCL(two))
DCHAL(one); DCHAL(two); I2 *ires;
{
register int i, j;
for(i=j=0; i<LEN(one) && i<LEN(two); i++)
if(CHA(one)[i]==CHA(two)[i]) j++;
*ires = j;
}
which is now the same thing as:
SUBROUTINE COUNTEQS(CHONE, CHTWO, IRES)
CHARACTER*(*) CHONE, CHTWO
INTEGER*2 IRES
INTEGER I,J
I=1
J=0
100 IF(I.gt.LEN(CHONE).or.I.gt.LEN(CHTWO)) GOTO 900
IF(CHONE(I:I).eq.CHTWO(I:I)) J=J+1
I=I+1
GOTO 100
900 IRES=J
RETURN
END
on all machines. Yes I know, the C-side syntax ain't exactly pretty,
but it's the only way we've found to keep C code interfacing to Fortran
bit-for-bit the same on all platforms we support, a task which had been
diagnosed as "absolutely impossible" by more than one "expert":-).
I would appreciate further discussion on this, but NO e-mail please -
we PAY for mail we get, and it's already costing me a pretty penny to
donate this to the fortran-cum-c community on the net!-).
--
Alex Martelli - CAD.LAB s.p.a., v. Stalingrado 53, Bologna, Italia
Email: (work:) staff at cadlab.sublink.org, (home:) alex at am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434;
Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).
More information about the Comp.lang.c
mailing list