staff@cadlab.sublink.ORG (Alex Martelli) (02/08/91)
springer@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@cadlab.sublink.org, (home:) alex@am.sublink.org Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; Fax: ++39 (51) 366964 (work only), Fidonet: 332/401.3 (home only).