mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
2050 lines
92 KiB
Plaintext
2050 lines
92 KiB
Plaintext
cfortran.doc 4.3
|
|
http://www-zeus.desy.de/~burow/cfortran/
|
|
Burkhard Burow burow@desy.de 1990 - 2001.
|
|
|
|
cfortran.h : Interfacing C or C++ and FORTRAN
|
|
|
|
Supports: Alpha and VAX VMS, Alpha OSF, DECstation and VAX Ultrix, IBM RS/6000,
|
|
Silicon Graphics, Sun, CRAY, Apollo, HP9000, LynxOS, Convex, Absoft,
|
|
f2c, g77, NAG f90, PowerStation Fortran with Visual C++, NEC SX-4,
|
|
Portland Group.
|
|
|
|
C and C++ are generally equivalent as far as cfortran.h is concerned.
|
|
Unless explicitly noted otherwise, mention of C implicitly includes C++.
|
|
C++ compilers tested include:
|
|
SunOS> CC +p +w # Clean compiles.
|
|
IRIX> CC # Clean compiles.
|
|
IRIX> CC -fullwarn # Still some warnings to be overcome.
|
|
GNU> g++ -Wall # Compiles are clean, other than warnings for unused
|
|
# cfortran.h static routines.
|
|
|
|
N.B.: The best documentation on interfacing C or C++ and Fortran is in
|
|
the chapter named something like 'Interfacing C and Fortran'
|
|
to be found in the user's guide of almost every Fortran compiler.
|
|
Understanding this information for one or more Fortran compilers
|
|
greatly clarifies the aims and actions of cfortran.h.
|
|
Such a chapter generally also addresses issues orthogonal to cfortran.h,
|
|
for example the order of array indices, the index of the first element,
|
|
as well as compiling and linking issues.
|
|
|
|
|
|
0 Short Summary of the Syntax Required to Create the Interface
|
|
--------------------------------------------------------------
|
|
|
|
e.g. Prototyping a FORTRAN subroutine for C:
|
|
|
|
/* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */
|
|
|
|
PROTOCCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT)
|
|
#define SUB_NAME(A,B) CCALLSFSUB2(SUB_NAME,sub_name,STRING,PINT, A,B)
|
|
|
|
^ - -
|
|
number of arguments _____| | STRING BYTE PBYTE BYTEV(..)|
|
|
/ | STRINGV DOUBLE PDOUBLE DOUBLEV(..)|
|
|
/ | PSTRING FLOAT PFLOAT FLOATV(..)|
|
|
types of arguments ____ / | PNSTRING INT PINT INTV(..)|
|
|
\ | PPSTRING LOGICAL PLOGICAL LOGICALV(..)|
|
|
\ | PSTRINGV LONG PLONG LONGV(..)|
|
|
\ | ZTRINGV SHORT PSHORT SHORTV(..)|
|
|
| PZTRINGV ROUTINE PVOID SIMPLE |
|
|
- -
|
|
|
|
|
|
e.g. Prototyping a FORTRAN function for C:
|
|
/* PROTOCCALLSFFUNn is mandatory for both C and C++. */
|
|
PROTOCCALLSFFUN1(INT,FUN_NAME,fun_name,STRING)
|
|
#define FUN_NAME(A) CCALLSFFUN1(FUN_NAME,fun_name,STRING, A)
|
|
|
|
e.g. calling FUN_NAME from C: {int a; a = FUN_NAME("hello");}
|
|
|
|
|
|
e.g. Creating a FORTRAN-callable wrapper for
|
|
a C function returning void, with a 7 dimensional integer array argument:
|
|
[Not supported from C++.]
|
|
FCALLSCSUB1(csub_name,CSUB_NAME,csub_name,INTVVVVVVV)
|
|
|
|
|
|
e.g. Creating a FORTRAN-callable wrapper for other C functions:
|
|
FCALLSCFUN1(STRING,cfun_name,CFUN_NAME,cfun_name,INT)
|
|
[ ^-- BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, VOID
|
|
are other types returned by functions. ]
|
|
|
|
|
|
e.g. COMMON BLOCKs:
|
|
FORTRAN: common /fcb/ v,w,x
|
|
character *(13) v, w(4), x(3,2)
|
|
C:
|
|
typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF;
|
|
#define FCB COMMON_BLOCK(FCB,fcb)
|
|
COMMON_BLOCK_DEF(FCB_DEF,FCB);
|
|
FCB_DEF FCB; /* Define, i.e. allocate memory, in exactly one *.c file. */
|
|
|
|
e.g. accessing FCB in C: printf("%.13s",FCB.v);
|
|
|
|
|
|
|
|
I Introduction
|
|
--------------
|
|
|
|
cfortran.h is an easy-to-use powerful bridge between C and FORTRAN.
|
|
It provides a completely transparent, machine independent interface between
|
|
C and FORTRAN routines (= subroutines and/or functions) and global data,
|
|
i.e. structures and COMMON blocks.
|
|
|
|
The complete cfortran.h package consists of 4 files: the documentation in
|
|
cfortran.doc, the engine cfortran.h, examples in cfortest.c and
|
|
cfortex.f/or. [cfortex.for under VMS, cfortex.f on other machines.]
|
|
|
|
The cfortran.h package continues to be developed. The most recent version is
|
|
available via www at http://www-zeus.desy.de/~burow/cfortran/
|
|
|
|
The examples may be run using one of the following sets of instructions:
|
|
|
|
N.B. Unlike earlier versions, cfortran.h 3.0 and later versions
|
|
automatically uses the correct ANSI ## or pre-ANSI /**/
|
|
preprocessor operator as required by the C compiler.
|
|
|
|
N.B. As a general rule when trying to determine how to link C and Fortran,
|
|
link a trivial Fortran program using the Fortran compilers verbose option,
|
|
in order to see how the Fortran compiler drives the linker. e.g.
|
|
unix> cat f.f
|
|
END
|
|
unix> f77 -v f.f
|
|
.. lots of info. follows ...
|
|
|
|
N.B. If using a C main(), i.e. Fortran PROGRAM is not entry of the executable,
|
|
and if the link bombs with a complaint about
|
|
a missing "MAIN" (e.g. MAIN__, MAIN_, f90_main or similar),
|
|
then Fortran has hijacked the entry point to the executable
|
|
and wishes to call the rest of the executable via "MAIN".
|
|
This can usually be satisfied by doing e.g. 'cc -Dmain=MAIN__ ...'
|
|
but often kills the command line arguments in argv and argc.
|
|
The f77 verbose option, usually -v, may point to a solution.
|
|
|
|
|
|
RS/6000> # Users are strongly urged to use f77 -qextname and cc -Dextname
|
|
RS/6000> # Use -Dextname=extname if extname is a symbol used in the C code.
|
|
RS/6000> xlf -c -qextname cfortex.f
|
|
RS/6000> cc -c -Dextname cfortest.c
|
|
RS/6000> xlf -o cfortest cfortest.o cfortex.o && cfortest
|
|
|
|
DECFortran> #Only DECstations with DECFortran for Ultrix RISC Systems.
|
|
DECFortran> cc -c -DDECFortran cfortest.c
|
|
DECFortran> f77 -o cfortest cfortest.o cfortex.f && cfortest
|
|
|
|
IRIX xxxxxx 5.2 02282015 IP20 mips
|
|
MIPS> # DECstations and Silicon Graphics using the MIPS compilers.
|
|
MIPS> cc -o cfortest cfortest.c cfortex.f -lI77 -lU77 -lF77 && cfortest
|
|
MIPS> # Can also let f77 drive linking, e.g.
|
|
MIPS> cc -c cfortest.c
|
|
MIPS> f77 -o cfortest cfortest.o cfortex.f && cfortest
|
|
|
|
Apollo> # Some 'C compiler 68K Rev6.8' break. [See Section II o) Notes: Apollo]
|
|
Apollo> f77 -c cfortex.f && cc -o cfortest cfortest.c cfortex.o && cfortest
|
|
|
|
VMS> define lnk$library sys$library:vaxcrtl
|
|
VMS> cc cfortest.c
|
|
VMS> fortran cfortex.for
|
|
VMS> link/exec=cfortest cfortest,cfortex
|
|
VMS> run cfortest
|
|
|
|
OSF1 xxxxxx V3.0 347 alpha
|
|
Alpha/OSF> # Probably better to let cc drive linking, e.g.
|
|
Alpha/OSF> f77 -c cfortex.f
|
|
Alpha/OSF> cc -o cfortest cfortest.c cfortex.o -lUfor -lfor -lFutil -lots -lm
|
|
Alpha/OSF> cfortest
|
|
Alpha/OSF> # Else may need 'cc -Dmain=MAIN__' to let f77 drive linking.
|
|
|
|
Sun> # Some old cc(1) need a little help. [See Section II o) Notes: Sun]
|
|
Sun> f77 -o cfortest cfortest.c cfortex.f -lc -lm && cfortest
|
|
Sun> # Some older f77 may require 'cc -Dmain=MAIN_'.
|
|
|
|
CRAY> cft77 cfortex.f
|
|
CRAY> cc -c cfortest.c
|
|
CRAY> segldr -o cfortest.e cfortest.o cfortex.o
|
|
CRAY> ./cfortest.e
|
|
|
|
NEC> cc -c -Xa cfortest.c
|
|
NEC> f77 -o cfortest cfortest.o cfortex.f && cfortest
|
|
|
|
VAX/Ultrix/cc> # For cc on VAX Ultrix only, do the following once to cfortran.h.
|
|
VAX/Ultrix/cc> mv cfortran.h cftmp.h && grep -v "^#pragma" <cftmp.h >cfortran.h
|
|
|
|
VAX/Ultrix/f77> # In the following, 'CC' is either 'cc' or 'gcc -ansi'. NOT'vcc'
|
|
VAX/Ultrix/f77> CC -c -Dmain=MAIN_ cfortest.c
|
|
VAX/Ultrix/f77> f77 -o cfortest cfortex.f cfortest.o && cfortest
|
|
|
|
LynxOS> # In the following, 'CC' is either 'cc' or 'gcc -ansi'.
|
|
LynxOS> # Unfortunately cc is easily overwhelmed by cfortran.h,
|
|
LynxOS> # and won't compile some of the cfortest.c demos.
|
|
LynxOS> f2c -R cfortex.f
|
|
LynxOS> CC -Dlynx -o cfortest cfortest.c cfortex.c -lf2c && cfortest
|
|
|
|
HP9000> # Tested with HP-UX 7.05 B 9000/380 and with A.08.07 A 9000/730
|
|
HP9000> # CC may be either 'c89 -Aa' or 'cc -Aa'
|
|
HP9000> # Depending on the compiler version, you may need to include the
|
|
HP9000> # option '-tp,/lib/cpp' or worse, you'll have to stick to the K&R C.
|
|
HP9000> # [See Section II o) Notes: HP9000]
|
|
HP9000> # Users are strongly urged to use f77 +ppu and cc -Dextname
|
|
HP9000> # Use -Dextname=extname if extname is a symbol used in the C code.
|
|
HP9000> CC -Dextname -c cfortest.c
|
|
HP9000> f77 +ppu cfortex.f -o cfortest cfortest.o && cfortest
|
|
HP9000> # Older f77 may need
|
|
HP9000> f77 -c cfortex.f
|
|
HP9000> CC -o cfortest cfortest.c cfortex.o -lI77 -lF77 && cfortest
|
|
|
|
HP0000> # If old-style f77 +800 compiled objects are required:
|
|
HP9000> # #define hpuxFortran800
|
|
HP9000> cc -c -Aa -DhpuxFortran800 cfortest.c
|
|
HP9000> f77 +800 -o cfortest cfortest.o cfortex.f
|
|
|
|
f2c> # In the following, 'CC' is any C compiler.
|
|
f2c> f2c -R cfortex.f
|
|
f2c> CC -o cfortest -Df2cFortran cfortest.c cfortex.c -lf2c && cfortest
|
|
|
|
Portland Group $ # Presumably other C compilers also work.
|
|
Portland Group $ pgcc -DpgiFortran -c cfortest.c
|
|
Portland Group $ pgf77 -o cfortest cfortex.f cfortest.o && cfortest
|
|
|
|
NAGf90> # cfortex.f is distributed with Fortran 77 style comments.
|
|
NAGf90> # To convert to f90 style comments do the following once to cfortex.f:
|
|
NAGf90> mv cfortex.f cf_temp.f && sed 's/^C/\!/g' cf_temp.f > cfortex.f
|
|
NAGf90> # In the following, 'CC' is any C compiler.
|
|
NAGf90> CC -c -DNAGf90Fortran cfortest.c
|
|
NAGf90> f90 -o cfortest cfortest.o cfortex.f && cfortest
|
|
|
|
PC> # On a PC with PowerStation Fortran and Visual_C++
|
|
PC> cl /c cftest.c
|
|
PC> fl32 cftest.obj cftex.for
|
|
|
|
GNU> # GNU Fortran
|
|
GNU> # See Section VI caveat on using 'gcc -traditional'.
|
|
GNU> gcc -ansi -Wall -O -c -Df2cFortran cfortest.c
|
|
GNU> g77 -ff2c -o cfortest cfortest.o cfortex.f && cfortest
|
|
|
|
AbsoftUNIX> # Absoft Fortran for all UNIX based operating systems.
|
|
AbsoftUNIX> # e.g. Linux or Next on Intel or Motorola68000.
|
|
AbsoftUNIX> # Absoft f77 -k allows Fortran routines to be safely called from C.
|
|
AbsoftUNIX> gcc -ansi -Wall -O -c -DAbsoftUNIXFortran cfortest.c
|
|
AbsoftUNIX> f77 -k -o cfortest cfortest.o cfortex.f && cfortest
|
|
|
|
AbsoftPro> # Absoft Pro Fortran for MacOS
|
|
AbsoftPro> # Use #define AbsoftProFortran
|
|
|
|
CLIPPER> # INTERGRAPH CLIX using CLIPPER C and Fortran compilers.
|
|
CLIPPER> # N.B. - User, not cfortran.h, is responsible for
|
|
CLIPPER> # f77initio() and f77uninitio() if required.
|
|
CLIPPER> # - LOGICAL values are not mentioned in CLIPPER doc.s,
|
|
CLIPPER> # so they may not yet be correct in cfortran.h.
|
|
CLIPPER> # - K&R mode (-knr or Ac=knr) breaks FLOAT functions
|
|
CLIPPER> # (see CLIPPER doc.s) and cfortran.h does not fix it up.
|
|
CLIPPER> # [cfortran.h ok for old sun C which made the same mistake.]
|
|
CLIPPER> acc cfortest.c -c -DCLIPPERFortran
|
|
CLIPPER> af77 cfortex.f cfortest.o -o cfortest
|
|
|
|
|
|
By changing the SELECTion ifdef of cfortest.c and recompiling one can try out
|
|
a few dozen different few-line examples.
|
|
|
|
|
|
|
|
The benefits of using cfortran.h include:
|
|
1. Machine/OS/compiler independent mixing of C and FORTRAN.
|
|
|
|
2. Identical (within syntax) calls across languages, e.g.
|
|
C FORTRAN
|
|
CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.)
|
|
/* C*/
|
|
HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.);
|
|
|
|
3. Each routine need only be set up once in its lifetime. e.g.
|
|
/* Setting up a FORTRAN routine to be called by C.
|
|
ID,...,VMX are merely the names of arguments.
|
|
These tags must be unique w.r.t. each other but are otherwise arbitrary. */
|
|
PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT)
|
|
#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \
|
|
CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \
|
|
ID,CHTITLE,NX,XMI,XMA,VMX)
|
|
|
|
4. Source code is NOT required for the C routines exported to FORTRAN, nor for
|
|
the FORTRAN routines imported to C. In fact, routines are most easily
|
|
prototyped using the information in the routines' documentation.
|
|
|
|
5. Routines, and the code calling them, can be coded naturally in the language
|
|
of choice. C routines may be coded with the natural assumption of being
|
|
called only by C code. cfortran.h does all the required work for FORTRAN
|
|
code to call C routines. Similarly it also does all the work required for C
|
|
to call FORTRAN routines. Therefore:
|
|
- C programmers need not embed FORTRAN argument passing mechanisms into
|
|
their code.
|
|
- FORTRAN code need not be converted into C code. i.e. The honed and
|
|
time-honored FORTRAN routines are called by C.
|
|
|
|
6. cfortran.h is a single ~1700 line C include file; portable to most
|
|
remaining, if not all, platforms.
|
|
|
|
7. STRINGS and VECTORS of STRINGS along with the usual simple arguments to
|
|
routines are supported as are functions returning STRINGS or numbers. Arrays
|
|
of pointers to strings and values of structures as C arguments, will soon be
|
|
implemented. After learning the machinery of cfortran.h, users can expand
|
|
it to create custom types of arguments. [This requires no modification to
|
|
cfortran.h, all the preprocessor directives required to implement the
|
|
custom types can be defined outside cfortran.h]
|
|
|
|
8. cfortran.h requires each routine to be exported to be explicitly set up.
|
|
While is usually only be done once in a header file it would be best if
|
|
applications were required to do no work at all in order to cross languages.
|
|
cfortran.h's simple syntax could be a convenient back-end for a program
|
|
which would export FORTRAN or C routines directly from the source code.
|
|
|
|
|
|
-----
|
|
|
|
Example 1 - cfortran.h has been used to make the C header file hbook.h,
|
|
which then gives any C programmer, e.g. example.c, full and
|
|
completely transparent access to CERN's HBOOK library of routines.
|
|
Each HBOOK routine required about 3 lines of simple code in
|
|
hbook.h. The example also demonstrates how FORTRAN common blocks
|
|
are defined and used.
|
|
|
|
/* hbook.h */
|
|
#include "cfortran.h"
|
|
:
|
|
PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT)
|
|
#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \
|
|
CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \
|
|
ID,CHTITLE,NX,XMI,XMA,VMX)
|
|
:
|
|
/* end hbook.h */
|
|
|
|
/* example.c */
|
|
#include "hbook.h"
|
|
:
|
|
typedef struct {
|
|
int lines;
|
|
int status[SIZE];
|
|
float p[SIZE]; /* momentum */
|
|
} FAKE_DEF;
|
|
#define FAKE COMMON_BLOCK(FAKE,fake)
|
|
COMMON_BLOCK_DEF(FAKE_DEF,FAKE);
|
|
:
|
|
main ()
|
|
{
|
|
:
|
|
HBOOK1(1,"pT spectrum of pi+",100,0.,5.,0.);
|
|
/* c.f. the call in FORTRAN:
|
|
CALL HBOOK1(1,'pT spectrum of pi+',100,0.,5.,0.)
|
|
*/
|
|
:
|
|
FAKE.p[7]=1.0;
|
|
:
|
|
}
|
|
|
|
N.B. i) The routine is language independent.
|
|
ii) hbook.h is machine independent.
|
|
iii) Applications using routines via cfortran.h are machine independent.
|
|
|
|
-----
|
|
|
|
Example 2 - Many VMS System calls are most easily called from FORTRAN, but
|
|
cfortran.h now gives that ease in C.
|
|
|
|
#include "cfortran.h"
|
|
|
|
PROTOCCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING)
|
|
#define LIB$SPAWN(command,input_file,output_file) \
|
|
CCALLSFSUB3(LIB$SPAWN,lib$spawn,STRING,STRING,STRING, \
|
|
command,input_file,output_file)
|
|
|
|
main ()
|
|
{
|
|
LIB$SPAWN("set term/width=132","","");
|
|
}
|
|
|
|
Obviously the cfortran.h command above could be put into a header file along
|
|
with the description of the other system calls, but as this example shows, it's
|
|
not much hassle to set up cfortran.h for even a single call.
|
|
|
|
-----
|
|
|
|
Example 3 - cfortran.h and the source cstring.c create the cstring.obj library
|
|
which gives FORTRAN access to all the functions in C's system
|
|
library described by the system's C header file string.h.
|
|
|
|
C EXAMPLE.FOR
|
|
PROGRAM EXAMPLE
|
|
DIMENSION I(20), J(30)
|
|
:
|
|
CALL MEMCPY(I,J,7)
|
|
:
|
|
END
|
|
|
|
/* cstring.c */
|
|
#include <string.h> /* string.h prototypes memcpy() */
|
|
#include "cfortran.h"
|
|
|
|
:
|
|
FCALLSCSUB3(memcpy,MEMCPY,memcpy,PVOID,PVOID,INT)
|
|
:
|
|
|
|
|
|
The simplicity exhibited in the above example exists for many but not all
|
|
machines. Note 4. of Section II ii) details the limitations and describes tools
|
|
which try to maintain the best possible interface when FORTRAN calls C
|
|
routines.
|
|
|
|
-----
|
|
|
|
|
|
II Using cfortran.h
|
|
-------------------
|
|
|
|
The user is asked to look at the source files cfortest.c and cfortex.f
|
|
for clarification by example.
|
|
|
|
o) Notes:
|
|
|
|
o Specifying the Fortran compiler
|
|
cfortran.h generates interfaces for the default Fortran compiler. The default
|
|
can be overridden by defining,
|
|
. in the code, e.g.: #define NAGf90Fortran
|
|
OR . in the compile directive, e.g.: unix> cc -DNAGf90Fortran
|
|
one of the following before including cfortran.h:
|
|
NAGf90Fortran f2cFortran hpuxFortran apolloFortran sunFortran
|
|
IBMR2Fortran CRAYFortran mipsFortran DECFortran vmsFortran
|
|
CONVEXFortran PowerStationFortran AbsoftUNIXFortran
|
|
SXFortran pgiFortran AbsoftProFortran
|
|
This also allows crosscompilation.
|
|
If wanted, NAGf90Fortran, f2cFortran, DECFortran, AbsoftUNIXFortran,
|
|
AbsoftProFortran and pgiFortran must be requested by the user.
|
|
|
|
o /**/
|
|
cfortran.h (ab)uses the comment kludge /**/ when the ANSI C preprocessor
|
|
catenation operator ## doesn't exist. In at least MIPS C, this kludge is
|
|
sensitive to blanks surrounding arguments to macros.
|
|
Therefore, for applications using non-ANSI C compilers, the argtype_i,
|
|
routine_name, routine_type and common_block_name arguments to the
|
|
PROTOCCALLSFFUNn, CCALLSFSUB/FUNn, FCALLSCSUB/FUNn and COMMON_BLOCK macros
|
|
--- MUST NOT --- be followed by any white space characters such as
|
|
blanks, tabs or newlines.
|
|
|
|
o LOGICAL
|
|
FORTRAN LOGICAL values of .TRUE. and .FALSE. do not agree with the C
|
|
representation of TRUE and FALSE on all machines. cfortran.h does the
|
|
conversion for LOGICAL and PLOGICAL arguments and for functions returning
|
|
LOGICAL. Users must convert arrays of LOGICALs from C to FORTRAN with the
|
|
C2FLOGICALV(array_name, elements_in_array); macro. Similarly, arrays of LOGICAL
|
|
values may be converted from the FORTRAN into C representation by using
|
|
F2CLOGICALV(array_name, elements_in_array);
|
|
|
|
When C passes or returns LOGICAL values to FORTRAN, by default cfortran.h
|
|
only makes the minimal changes required to the value. [e.g. Set/Unset the
|
|
single relevant bit or do nothing for FORTRAN compilers which use 0 as FALSE
|
|
and treat all other values as TRUE.] Therefore cfortran.h will pass LOGICALs
|
|
to FORTRAN which do not have an identical representation to .TRUE. or .FALSE.
|
|
This is fine except for abuses of FORTRAN/77 in the style of:
|
|
logical l
|
|
if (l .eq. .TRUE.) ! (1)
|
|
instead of the correct:
|
|
if (l .eqv. .TRUE.) ! (2)
|
|
or:
|
|
if (l) ! (3)
|
|
For FORTRAN code which treats LOGICALs from C in the method of (1),
|
|
LOGICAL_STRICT must be defined before including cfortran.h, either in the
|
|
code, "#define LOGICAL_STRICT", or compile with "cc -DLOGICAL_STRICT".
|
|
There is no reason to use LOGICAL_STRICT for FORTRAN code which does not do (1).
|
|
At least the IBM's xlf and the Apollo's f77 do not even allow code along the
|
|
lines of (1).
|
|
|
|
DECstations' DECFortran and MIPS FORTRAN compilers use different internal
|
|
representations for LOGICAL values. [Both compilers are usually called f77,
|
|
although when both are installed on a single machine the MIPS' one is usually
|
|
renamed. (e.g. f772.1 for version 2.10.)] cc doesn't know which FORTRAN
|
|
compiler is present, so cfortran.h assumes MIPS f77. To use cc with DECFortran
|
|
define the preprocessor constant 'DECFortran'.
|
|
e.g. i) cc -DDECFortran -c the_code.c
|
|
or ii) #define DECFortran /* in the C code or add to cfortran.h. */
|
|
|
|
MIPS f77 [SGI and DECstations], f2c, and f77 on VAX Ultrix treat
|
|
.eqv./.neqv. as .eq./.ne.. Therefore, for these compilers, LOGICAL_STRICT is
|
|
defined by default in cfortran.h. [The Sun and HP compilers have not been
|
|
tested, so they may also require LOGICAL_STRICT as the default.]
|
|
|
|
o SHORT and BYTE
|
|
They are irrelevant for the CRAY where FORTRAN has no equivalent to C's short.
|
|
Similarly BYTE is irrelevant for f2c and for VAX Ultrix f77 and fort. The
|
|
author has tested SHORT and BYTE with a modified cfortest.c/cfortex.f on all
|
|
machines supported except for the HP9000 and the Sun.
|
|
|
|
BYTE is a signed 8-bit quantity, i.e. values are -128 to 127, on all machines
|
|
except for the SGI [at least for MIPS Computer Systems 2.0.] On the SGI it is
|
|
an unsigned 8-bit quantity, i.e. values are 0 to 255, although the SGI 'FORTRAN
|
|
77 Programmers Guide' claims BYTE is signed. Perhaps MIPS 2.0 is dated, since
|
|
the DECstations using MIPS 2.10 f77 have a signed BYTE.
|
|
|
|
To minimize the difficulties of signed and unsigned BYTE, cfortran.h creates
|
|
the type 'INTEGER_BYTE' to agree with FORTRAN's BYTE. Users may define
|
|
SIGNED_BYTE or UNSIGNED_BYTE, before including cfortran.h, to specify FORTRAN's
|
|
BYTE. If neither is defined, cfortran.h assumes SIGNED_BYTE.
|
|
|
|
o CRAY
|
|
The type DOUBLE in cfortran.h corresponds to FORTRAN's DOUBLE PRECISION.
|
|
The type FLOAT in cfortran.h corresponds to FORTRAN's REAL.
|
|
|
|
On a classic CRAY [i.e. all models except for the t3e]:
|
|
( 64 bit) C float == C double == Fortran REAL
|
|
(128 bit) C long double == Fortran DOUBLE PRECISION
|
|
Therefore when moving a mixed C and FORTRAN app. to/from a classic CRAY,
|
|
either the C code will have to change,
|
|
or the FORTRAN code and cfortran.h declarations will have to change.
|
|
DOUBLE_PRECISION is a cfortran.h macro which provides the former option,
|
|
i.e. the C code is automatically changed.
|
|
DOUBLE_PRECISION is 'long double' on classic CRAY and 'double' elsewhere.
|
|
DOUBLE_PRECISION thus corresponds to FORTRAN's DOUBLE PRECISION
|
|
on all machines, including classic CRAY.
|
|
|
|
On a classic CRAY with the fortran compiler flag '-dp':
|
|
Fortran DOUBLE PRECISION thus is also the faster 64bit type.
|
|
(This switch is often used since the application is usually satisfied by
|
|
64 bit precision and the application needs the speed.)
|
|
DOUBLE_PRECISION is thus not required in this case,
|
|
since the classic CRAY behaves like all other machines.
|
|
If DOUBLE_PRECISION is used nonetheless, then on the classic CRAY
|
|
the default cfortran.h behavior must be overridden,
|
|
for example by the C compiler option '-DDOUBLE_PRECISION=double'.
|
|
|
|
On a CRAY t3e:
|
|
(32 bit) C float == Fortran Unavailable
|
|
(64 bit) C double == C long double == Fortran REAL == Fortran DOUBLE PRECISION
|
|
Notes:
|
|
- (32 bit) is available as Fortran REAL*4 and
|
|
(64 bit) is available as Fortran REAL*8.
|
|
Since cfortran.h is all about more portability, not about less portability,
|
|
the use of the nonstandard REAL*4 and REAL*8 is strongly discouraged.
|
|
- Fortran DOUBLE PRECISION is folded to REAL with the following warning:
|
|
'DOUBLE PRECISION is not supported on this platform. REAL will be used.'
|
|
Similarly, Fortran REAL*16 is mapped to REAL*8 with a warning.
|
|
This behavior differs from that of other machines, including the classic CRAY.
|
|
FORTRAN_REAL is thus introduced for the t3e,
|
|
just as DOUBLE_PRECISION is introduced for the classic CRAY.
|
|
FORTRAN_REAL is 'double' on t3e and 'float' elsewhere.
|
|
FORTRAN_REAL thus corresponds to FORTRAN's REAL on all machines, including t3e.
|
|
|
|
|
|
o f2c
|
|
f2c, by default promotes REAL functions to double. cfortran.h does not (yet)
|
|
support this, so the f2c -R option must be used to turn this promotion off.
|
|
|
|
o f2c
|
|
[Thanks to Dario Autiero for pointing out the following.]
|
|
f2c has a strange feature in that either one or two underscores are appended
|
|
to a Fortran name of a routine or common block,
|
|
depending on whether or not the original name contains an underscore.
|
|
|
|
S.I. Feldman et al., "A fortran to C converter",
|
|
Computing Science Technical Report No. 149.
|
|
|
|
page 2, chapter 2: INTERLANGUAGE conventions
|
|
...........
|
|
To avoid conflict with the names of library routines and with names that
|
|
f2c generates,
|
|
Fortran names may have one or two underscores appended. Fortran names are
|
|
forced to lower case (unless the -U option described in Appendix B is in
|
|
effect); external names, i.e. the names of fortran procedures and common
|
|
blocks, have a single underscore appended if they do not contain any
|
|
underscore and have a pair of underscores appended if they do contain
|
|
underscores. Thus fortran subroutines names ABC, A_B_C and A_B_C_ result
|
|
in C functions named abc_, a_b_c__ and a_b_c___.
|
|
...........
|
|
|
|
cfortran.h is unable to change the naming convention on a name by name basis.
|
|
Fortran routine and common block names which do not contain an underscore
|
|
are unaffected by this feature.
|
|
Names which do contain an underscore may use the following work-around:
|
|
|
|
/* First 2 lines are a completely standard cfortran.h interface
|
|
to the Fortran routine E_ASY . */
|
|
PROTOCCALLSFSUB2(E_ASY,e_asy, PINT, INT)
|
|
#define E_ASY(A,B) CCALLSFSUB2(E_ASY,e_asy, PINT, INT, A, B)
|
|
#ifdef f2cFortran
|
|
#define e_asy_ e_asy__
|
|
#endif
|
|
/* Last three lines are a work-around for the strange f2c naming feature. */
|
|
|
|
o NAG f90
|
|
The Fortran 77 subset of Fortran 90 is supported. Extending cfortran.h to
|
|
interface C with all of Fortran 90 has not yet been examined.
|
|
The NAG f90 library hijacks the main() of any program and starts the user's
|
|
program with a call to: void f90_main(void);
|
|
While this in itself is only a minor hassle, a major problem arises because
|
|
NAG f90 provides no mechanism to access command line arguments.
|
|
At least version 'NAGWare f90 compiler Version 1.1(334)' appended _CB to
|
|
common block names instead of the usual _. To fix, add this to cfortran.h:
|
|
#ifdef old_NAG_f90_CB_COMMON
|
|
#define COMMON_BLOCK CFC_ /* for all other Fortran compilers */
|
|
#else
|
|
#define COMMON_BLOCK(UN,LN) _(LN,_CB)
|
|
#endif
|
|
|
|
o RS/6000
|
|
Using "xlf -qextname ...", which appends an underscore, '_', to all FORTRAN
|
|
external references, requires "cc -Dextname ..." so that cfortran.h also
|
|
generates these underscores.
|
|
Use -Dextname=extname if extname is a symbol used in the C code.
|
|
The use of "xlf -qextname" is STRONGLY ENCOURAGED, since it allows for
|
|
transparent naming schemes when mixing C and Fortran.
|
|
|
|
o HP9000
|
|
Using "f77 +ppu ...", which appends an underscore, '_', to all FORTRAN
|
|
external references, requires "cc -Dextname ..." so that cfortran.h also
|
|
generates these underscores.
|
|
Use -Dextname=extname if extname is a symbol used in the C code.
|
|
The use of "f77 +ppu" is STRONGLY ENCOURAGED, since it allows for
|
|
transparent naming schemes when mixing C and Fortran.
|
|
|
|
At least one release of the HP /lib/cpp.ansi preprocessor is broken and will
|
|
go into an infinite loop when trying to process cfortran.h with the
|
|
## catenation operator. The K&R version of cfortran.h must then be used and the
|
|
K&R preprocessor must be specified. e.g.
|
|
HP9000> cc -Aa -tp,/lib/cpp -c source.c
|
|
The same problem with a similar solution exists on the Apollo.
|
|
An irrelevant error message '0: extraneous name /usr/include' will appear for
|
|
each source file due to another HP bug, and can be safely ignored.
|
|
e.g. 'cc -v -c -Aa -tp,/lib/cpp cfortest.c' will show that the driver passes
|
|
'-I /usr/include' instead of '-I/usr/include' to /lib/cpp
|
|
|
|
On some machines the above error causes compilation to stop; one must then use
|
|
K&R C, as with old HP compilers which don't support function prototyping.
|
|
cfortran.h has to be informed that K&R C is to being used, e.g.
|
|
HP9000> cc -D__CF__KnR -c source.c
|
|
|
|
o AbsoftUNIXFortran
|
|
By default, cfortran.h follows the default AbsoftUNIX/ProFortran and prepends _C
|
|
to each COMMON BLOCK name. To override the cfortran.h behavior
|
|
#define COMMON_BLOCK(UN,LN) before #including cfortran.h.
|
|
[Search for COMMON_BLOCK in cfortran.h for examples.]
|
|
|
|
o Apollo
|
|
On at least one release, 'C compiler 68K Rev6.8(168)', the default C
|
|
preprocessor, from cc -A xansi or cc -A ansi, enters an infinite loop when
|
|
using cfortran.h. This Apollo bug can be circumvented by using:
|
|
. cc -DANSI_C_preprocessor=0 to force use of /**/, instead of '##'.
|
|
AND . The pre-ANSI preprocessor, i.e. use cc -Yp,/usr/lib
|
|
The same problem with a similar solution exists on the HP.
|
|
|
|
o Sun
|
|
Old versions of cc(1), say <~1986, may require help for cfortran.h applications:
|
|
. #pragma may not be understood, hence cfortran.h and cfortest.c may require
|
|
sun> mv cfortran.h cftmp.h && grep -v "^#pragma" <cftmp.h >cfortran.h
|
|
sun> mv cfortest.c cftmp.c && grep -v "^#pragma" <cftmp.c >cfortest.c
|
|
. Old copies of math.h may not include the following from a newer math.h.
|
|
[For an ancient math.h on a 386 or sparc, get similar from a new math.h.]
|
|
#ifdef mc68000 /* 5 lines Copyright (c) 1988 by Sun Microsystems, Inc. */
|
|
#define FLOATFUNCTIONTYPE int
|
|
#define RETURNFLOAT(x) return (*(int *)(&(x)))
|
|
#define ASSIGNFLOAT(x,y) *(int *)(&x) = y
|
|
#endif
|
|
|
|
o CRAY, Sun, Apollo [pre 6.8 cc], VAX Ultrix and HP9000
|
|
Only FORTRAN routines with less than 15 arguments can be prototyped for C,
|
|
since these compilers don't allow more than 31 arguments to a C macro. This can
|
|
be overcome, [see Section IV], with access to any C compiler without this
|
|
limitation, e.g. gcc, on ANY machine.
|
|
|
|
o VAX Ultrix
|
|
vcc (1) with f77 is not supported. Although:
|
|
VAXUltrix> f77 -c cfortex.f
|
|
VAXUltrix> vcc -o cfortest cfortest.c cfortex.o -lI77 -lU77 -lF77 && cfortest
|
|
will link and run. However, the FORTRAN standard I/O is NOT merged with the
|
|
stdin and stdout of C, and instead uses the files fort.6 and fort.5. For vcc,
|
|
f77 can't drive the linking, as for gcc and cc, since vcc objects must be
|
|
linked using lk (1). f77 -v doesn't tell much, and without VAX Ultrix manuals,
|
|
the author can only wait for the info. required.
|
|
|
|
fort (1) is not supported. Without VAX Ultrix manuals the author cannot
|
|
convince vcc/gcc/cc and fort to generate names of routines and COMMON blocks
|
|
that match at the linker, lk (1). i.e. vcc/gcc/cc prepend a single underscore
|
|
to external references, e.g. NAME becomes _NAME, while fort does not modify the
|
|
references. So ... either fort has prepend an underscore to external
|
|
references, or vcc/gcc/cc have to generate unmodified names. man 1 fort
|
|
mentions JBL, is JBL the only way?
|
|
|
|
o VAX VMS C
|
|
The compiler 'easily' exhausts its table space and generates:
|
|
%CC-F-BUGCHECK, Compiler bug check during parser phase .
|
|
Submit an SPR with a problem description.
|
|
At line number 777 in DISK:[DIR]FILE.C;1.
|
|
where the line given, '777', includes a call across C and FORTRAN via
|
|
cfortran.h, usually with >7 arguments and/or very long argument expressions.
|
|
This SPR can be staved off, with the simple modification to cfortran.h, such
|
|
that the relevant CCALLSFSUBn (or CCALLSFFUNn or FCALLSCFUNn) is not
|
|
cascaded up to CCALLSFSUB14, and instead has its own copy of the contents of
|
|
CCALLSFSUB14. [If these instructions are not obvious after examining cfortran.h
|
|
please contact the author.]
|
|
[Thanks go to Mark Kyprianou (kyp@stsci.edu) for this solution.]
|
|
|
|
o Mips compilers
|
|
e.g. DECstations and SGI, require applications with a C main() and calls to
|
|
GETARG(3F), i.e. FORTRAN routines returning the command line arguments, to use
|
|
two macros as shown:
|
|
:
|
|
CF_DECLARE_GETARG; /* This must be external to all routines. */
|
|
:
|
|
main(int argc, char *argv[])
|
|
{
|
|
:
|
|
CF_SET_GETARG(argc,argv); /* This must precede any calls to GETARG(3F). */
|
|
:
|
|
}
|
|
The macros are null and benign on all other systems. Sun's GETARG(3F) also
|
|
doesn't work with a generic C main() and perhaps a workaround similar to the
|
|
Mips' one exists.
|
|
|
|
o Alpha/OSF
|
|
Using the DEC Fortran and the DEC C compilers of DEC OSF/1 [RT] V1.2 (Rev. 10),
|
|
Fortran, when called from C, has occasional trouble using a routine received as
|
|
a dummy argument.
|
|
|
|
e.g. In the following the Fortran routine 'e' will crash when it tries to use
|
|
the C routine 'c' or the Fortran routine 'f'.
|
|
The example works on other systems.
|
|
|
|
C FORTRAN /* C */
|
|
integer function f() #include <stdio.h>
|
|
f = 2 int f_();
|
|
return int e_(int (*u)());
|
|
end
|
|
int c(){ return 1;}
|
|
integer function e(u) int d (int (*u)()) { return u();}
|
|
integer u
|
|
external u main()
|
|
e=u() { /* Calls to d work. */
|
|
return printf("d (c ) returns %d.\n",d (c ));
|
|
end printf("d (f_) returns %d.\n",d (f_));
|
|
/* Calls to e_ crash. */
|
|
printf("e_(c ) returns %d.\n",e_(c ));
|
|
printf("e_(f_) returns %d.\n",e_(f_));
|
|
}
|
|
|
|
Solutions to the problem are welcomed!
|
|
A kludge which allows the above example to work correctly, requires an extra
|
|
argument to be given when calling the dummy argument function.
|
|
i.e. Replacing 'e=u()' by 'e=u(1)' allows the above example to work.
|
|
|
|
|
|
o The FORTRAN routines are called using macro expansions, therefore the usual
|
|
caveats for expressions in arguments apply. The expressions to the routines may
|
|
be evaluated more than once, leading to lower performance and in the worst case
|
|
bizarre bugs.
|
|
|
|
o For those who wish to use cfortran.h in large applications. [See Section IV.]
|
|
This release is intended to make it easy to get applications up and running.
|
|
This implies that applications are not as efficient as they could be:
|
|
- The current mechanism is inefficient if a single header file is used to
|
|
describe a large library of FORTRAN functions. Code for a static wrapper fn.
|
|
is generated in each piece of C source code for each FORTRAN function
|
|
specified with the CCALLSFFUNn statement, irrespective of whether or not the
|
|
function is ever called.
|
|
- Code for several static utility routines internal to cfortran.h is placed
|
|
into any source code which #includes cfortran.h. These routines should
|
|
probably be in a library.
|
|
|
|
|
|
i) Calling FORTRAN routines from C:
|
|
--------------------------------
|
|
|
|
The FORTRAN routines are defined by one of the following two instructions:
|
|
|
|
for a SUBROUTINE:
|
|
/* PROTOCCALLSFSUBn is optional for C, but mandatory for C++. */
|
|
PROTOCCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n)
|
|
#define Routine_name(argname_1,..,argname_n) \
|
|
CCALLSFSUBn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \
|
|
argname_1,..,argname_n)
|
|
|
|
for a FUNCTION:
|
|
PROTOCCALLSFFUNn(routine_type,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n)
|
|
#define Routine_name(argname_1,..,argname_n) \
|
|
CCALLSFFUNn(ROUTINE_NAME,routine_name,argtype_1,...,argtype_n, \
|
|
argname_1,..,argname_n)
|
|
|
|
Where:
|
|
'n' = 0->14 [SUBROUTINE's ->27] (easily expanded in cfortran.h to > 14 [27]) is
|
|
the number of arguments to the routine.
|
|
Routine_name = C name of the routine (IN UPPER CASE LETTERS).[see 2.below]
|
|
ROUTINE_NAME = FORTRAN name of the routine (IN UPPER CASE LETTERS).
|
|
routine_name = FORTRAN name of the routine (IN lower case LETTERS).
|
|
routine_type = the type of argument returned by FORTRAN functions.
|
|
= BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID.
|
|
[Instead of VOID one would usually use CCALLSFSUBn.
|
|
VOID forces a wrapper function to be used.]
|
|
argtype_i = the type of argument passed to the FORTRAN routine and must be
|
|
consistent in the definition and prototyping of the routine s.a.
|
|
= BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING.
|
|
For vectors, i.e. 1 dim. arrays use
|
|
= BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV,
|
|
STRINGV, ZTRINGV.
|
|
For vectors of vectors, i.e. 2 dim. arrays use
|
|
= BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV.
|
|
For n-dim. arrays, 1<=n<=7 [7 is the maximum in Fortran 77],
|
|
= BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V,
|
|
LONGV..V, SHORTV..V.
|
|
N.B. Array dimensions and types are checked by the C compiler.
|
|
For routines changing the values of an argument, the keyword is
|
|
prepended by a 'P'.
|
|
= PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT,
|
|
PSTRING, PSTRINGV, PZTRINGV.
|
|
For EXTERNAL procedures passed as arguments use
|
|
= ROUTINE.
|
|
For exceptional arguments which require no massaging to fit the
|
|
argument passing mechanisms use
|
|
= PVOID.
|
|
The argument is cast and passed as (void *).
|
|
Although PVOID could be used to describe all array arguments on
|
|
most (all?) machines , it shouldn't be because the C compiler
|
|
can no longer check the type and dimension of the array.
|
|
argname_i = any valid unique C tag, but must be consistent in the definition
|
|
as shown.
|
|
|
|
Notes:
|
|
|
|
1. cfortran.h may be expanded to handle a more argument type. To suppport new
|
|
arguments requiring complicated massaging when passed between Fortran and C,
|
|
the user will have to understand cfortran.h and follow its code and mechanisms.
|
|
|
|
To define types requiring little or no massaging when passed between Fortran
|
|
and C, the pseudo argument type SIMPLE may be used.
|
|
For a user defined type called 'newtype', the definitions required are:
|
|
|
|
/* The following 7 lines are required verbatim.
|
|
'newtype' is the name of the new user defined argument type.
|
|
*/
|
|
#define newtype_cfV( T,A,B,F) SIMPLE_cfV(T,A,B,F)
|
|
#define newtype_cfSEP(T, B) SIMPLE_cfSEP(T,B)
|
|
#define newtype_cfINT(N,A,B,X,Y,Z) SIMPLE_cfINT(N,A,B,X,Y,Z)
|
|
#define newtype_cfSTR(N,T,A,B,C,D,E) SIMPLE_cfSTR(N,T,A,B,C,D,E)
|
|
#define newtype_cfCC( T,A,B) SIMPLE_cfCC(T,A,B)
|
|
#define newtype_cfAA( T,A,B) newtype_cfB(T,A) /* Argument B not used. */
|
|
#define newtype_cfU( T,A) newtype_cfN(T,A)
|
|
|
|
/* 'parameter_type(A)' is a declaration for 'A' and describes the type of the
|
|
parameter expected by the Fortran function. This type will be used in the
|
|
prototype for the function, if using ANSI C, and to declare the argument used
|
|
by the intermediate function if calling a Fortran FUNCTION.
|
|
Valid 'parameter_type(A)' include: int A
|
|
void (*A)()
|
|
double A[17]
|
|
*/
|
|
#define newtype_cfN( T,A) parameter_type(A) /* Argument T not used. */
|
|
|
|
/* Before any argument of the new type is passed to the Fortran routine, it may
|
|
be massaged as given by 'massage(A)'.
|
|
*/
|
|
#define newtype_cfB( T,A) massage(A) /* Argument T not used. */
|
|
|
|
An example of a simple user defined type is given cfortex.f and cfortest.c.
|
|
Two uses of SIMPLE user defined types are [don't show the 7 verbatim #defines]:
|
|
|
|
/* Pass the address of a structure, using a type called PSTRUCT */
|
|
#define PSTRUCT_cfN( T,A) void *A
|
|
#define PSTRUCT_cfB( T,A) (void *) &(A)
|
|
|
|
/* Pass an integer by value, (not standard F77 ), using a type called INTVAL */
|
|
#define INTVAL_cfN( T,A) int A
|
|
#define INTVAL_cfB( T,A) (A)
|
|
|
|
[If using VAX VMS, surrounding the #defines with "#pragma (no)standard" allows
|
|
the %CC-I-PARAMNOTUSED messages to be avoided.]
|
|
|
|
Upgrades to cfortran.h try to be, and have been, backwards compatible. This
|
|
compatibility cannot be offered to user defined types. SIMPLE user defined
|
|
types are less of a risk since they require so little effort in their creation.
|
|
If a user defined type is required in more than one C header file of interfaces
|
|
to libraries of Fortran routines, good programming practice, and ease of code
|
|
maintenance, suggests keeping any user defined type within a single file which
|
|
is #included as required. To date, changes to the SIMPLE macros were introduced
|
|
in versions 2.6, 3.0 and 3.2 of cfortran.h.
|
|
|
|
|
|
2. Routine_name is the name of the macro which the C programmer will use in
|
|
order to call a FORTRAN routine. In theory Routine_name could be any valid and
|
|
unique name, but in practice, the name of the FORTRAN routine in UPPER CASE
|
|
works everywhere and would seem to be an obvious choice.
|
|
|
|
|
|
3. <BYTE|DOUBLE|BYTE|DOUBLE|FLOAT|INT|LOGICAL|LONG|SHORT><V|VV|VVV|...>
|
|
|
|
cfortran.h encourages the exact specification of the type and dimension of
|
|
array parameters because it allows the C compiler to detect errors in the
|
|
arguments when calling the routine.
|
|
|
|
cfortran.h does not strictly require the exact specification since the argument
|
|
is merely the address of the array and is passed on to the calling routine.
|
|
Any array parameter could be declared as PVOID, but this circumvents
|
|
C's compiletime ability to check the correctness of arguments and is therefore
|
|
discouraged.
|
|
|
|
Passing the address of these arguments implies that PBYTEV, PFLOATV, ... ,
|
|
PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the
|
|
calling code share the same array, i.e. the same values at the same memory
|
|
location.
|
|
|
|
These comments do NOT apply to arrays of (P)S/ZTRINGV. For these parameters,
|
|
cfortran.h passes a massaged copy of the array to the routine. When the routine
|
|
returns, S/ZTRINGV ignores the copy, while PS/ZTRINGV replaces the calling
|
|
code's original array with copy, which may have been modified by the called
|
|
routine.
|
|
|
|
|
|
4. (P)STRING(V):
|
|
- STRING - If the argument is a fixed length character array, e.g. char ar[8];,
|
|
the string is blank, ' ', padded on the right to fill out the array before
|
|
being passed to the FORTRAN routine. The useful size of the string is the same
|
|
in both languages, e.g. ar[8] is passed as character*7. If the argument is a
|
|
pointer, the string cannot be blank padded, so the length is passed as
|
|
strlen(argument). On return from the FORTRAN routine, pointer arguments are not
|
|
disturbed, but arrays have the terminating '\0' replaced to its original
|
|
position. i.e. The padding blanks are never visible to the C code.
|
|
|
|
- PSTRING - The argument is massaged as with STRING before being passed to the
|
|
FORTRAN routine. On return, the argument has all trailing blanks removed,
|
|
regardless of whether the argument was a pointer or an array.
|
|
|
|
- (P)STRINGV - Passes a 1- or 2-dimensional char array. e.g. char a[7],b[6][8];
|
|
STRINGV may thus also pass a string constant, e.g. "hiho".
|
|
(P)STRINGV does NOT pass a pointer, e.g. char *, to either a 1- or a
|
|
2-dimensional array, since it cannot determine the array dimensions.
|
|
A pointer can only be passed using (P)ZTRINGV.
|
|
N.B. If a C routine receives a character array argument, e.g. char a[2][3],
|
|
such an argument is actually a pointer and my thus not be passed by
|
|
(P)STRINGV. Instead (P)ZTRINGV must be used.
|
|
|
|
- STRINGV - The elements of the argument are copied into space malloc'd, and
|
|
each element is padded with blanks. The useful size of each element is the same
|
|
in both languages. Therefore char bb[6][8]; is equivalent to character*7 bb(6).
|
|
On return from the routine the malloc'd space is simply released.
|
|
|
|
- PSTRINGV - Since FORTRAN has no trailing '\0', elements in an array of
|
|
strings are contiguous. Therefore each element of the C array is padded with
|
|
blanks and strip out C's trailing '\0'. After returning from the routine, the
|
|
trailing '\0' is reinserted and kill the trailing blanks in each element.
|
|
|
|
- SUMMARY: STRING(V) arguments are blank padded during the call to the FORTRAN
|
|
routine, but remain original in the C code. (P)STRINGV arguments are blank
|
|
padded for the FORTRAN call, and after returning from FORTRAN trailing blanks
|
|
are stripped off.
|
|
|
|
|
|
5. (P)ZTRINGV:
|
|
- (P)ZTRINGV - is identical to (P)STRINGV,
|
|
except that the dimensions of the array of strings is explicitly specified,
|
|
which thus also allows a pointer to be passed.
|
|
(P)ZTRINGV can thus pass a 1- or 2-dimensional char array, e.g. char b[6][8],
|
|
or it can pass a pointer to such an array, e.g. char *p;.
|
|
ZTRINGV may thus also pass a string constant, e.g. "hiho".
|
|
If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1.
|
|
[Users of (P)ZTRINGV should examine cfortest.c for examples.]:
|
|
|
|
- (P)ZTRINGV must thus be used instead of (P)STRINGV whenever sizeof()
|
|
can't be used to determine the dimensions of the array of string or strings.
|
|
e.g. when calling FORTRAN from C with a char * received by C as an argument.
|
|
|
|
- There is no (P)ZTRING type, since (P)ZTRINGV can pass a 1-dimensional
|
|
array or a pointer to such an array, e.g. char a[7], *b;
|
|
If passing a 1-dimensional array, routine_name_ELEMS_j (see below) must be 1.
|
|
|
|
- To specify the numbers of elements,
|
|
routine_name_ELEMS_j and routine_name_ELEMLEN_j must be defined as shown below
|
|
before interfacing the routine with CCALLSFSUBn, PROTOCCALLSFFUNn, etc.
|
|
|
|
#define routine_name_ELEMS_j ZTRINGV_ARGS(k)
|
|
[..ARGS for subroutines, ..ARGF for functions.]
|
|
or
|
|
#define routine_name_ELEMS_j ZTRINGV_NUM(l)
|
|
Where: routine_name is as above.
|
|
j [1-n], is the argument being specifying.
|
|
k [1-n], the value of the k'th argument is the dynamic number
|
|
of elements for argument j. The k'th argument must be
|
|
of type BYTE, DOUBLE, FLOAT, INT, LONG or SHORT.
|
|
l the number of elements for argument j. This must be an
|
|
integer constant available at compile time.
|
|
i.e. it is static.
|
|
|
|
- Similarly to specify the useful length, [i.e. don't count C's trailing '\0',]
|
|
of each element:
|
|
#define routine_name_ELEMLEN_j ZTRINGV_ARGS(m)
|
|
[..ARGS for subroutines, ..ARGF for functions.]
|
|
or
|
|
#define routine_name_ELEMLEN_j ZTRINGV_NUM(q)
|
|
Where: m [1-n], as for k but this is the length of each element.
|
|
q as for l but this is the length of each element.
|
|
|
|
|
|
6. ROUTINE
|
|
The argument is an EXTERNAL procedure.
|
|
|
|
When C passes a routine to Fortran, the language of the function must be
|
|
specified as follows: [The case of some_*_function must be given as shown.]
|
|
|
|
When C passes a C routine to a Fortran:
|
|
FORTRAN_ROUTINE(arg1, .... ,
|
|
C_FUNCTION(SOME_C_FUNCTION,some_c_function),
|
|
...., argn);
|
|
|
|
and similarly when C passes a Fortran routine to Fortran:
|
|
FORTRAN_ROUTINE(arg1, .... ,
|
|
FORTRAN_FUNCTION(SOME_FORT_FUNCTION,some_fort_function),
|
|
...., argn);
|
|
|
|
If fcallsc has been redefined; the same definition of fcallsc used when creating
|
|
the wrapper for 'some_c_function' must also be defined when C_FUNCTION is used.
|
|
See ii) 4. of this section for when and how to redefine fcallsc.
|
|
|
|
ROUTINE was introduced with cfortran.h version 2.6. Earlier versions of
|
|
cfortran.h used PVOID to pass external procedures as arguments. Using PVOID for
|
|
this purpose is no longer recommended since it won't work 'as is' for
|
|
apolloFortran, hpuxFortran800, AbsoftUNIXFortran, AbsoftProFortran.
|
|
|
|
7. CRAY only:
|
|
In a given piece of source code, where FFUNC is any FORTRAN routine,
|
|
FORTRAN_FUNCTION(FFUNC,ffunc)
|
|
disallows a previous
|
|
#define FFUNC(..) CCALLSFSUBn(FFUNC,ffunc,...) [ or CCALLSFFUNn]
|
|
in order to make the UPPER CASE FFUNC callable from C.
|
|
#define Ffunc(..) ... is OK though, as are obviously any other names.
|
|
|
|
|
|
ii) Calling C routines from FORTRAN:
|
|
--------------------------------
|
|
|
|
Each of the following two statements to export a C routine to FORTRAN create
|
|
FORTRAN 'wrappers', written in C, which must be compiled and linked along with
|
|
the original C routines and with the FORTRAN calling code.
|
|
|
|
FORTRAN callable 'wrappers' may also be created for C macros. i.e. in this
|
|
section, the term 'C function' may be replaced by 'C macro'.
|
|
|
|
for C functions returning void:
|
|
FCALLSCSUBn( Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n)
|
|
|
|
for all other C functions:
|
|
FCALLSCFUNn(routine_type,Routine_name,ROUTINE_NAME,routine_name,argtype_1,...,argtype_n)
|
|
|
|
Where:
|
|
'n' = 0->27 (easily expanded to > 27) stands for the number of arguments to the
|
|
routine.
|
|
Routine_name = the C name of the routine. [see 9. below]
|
|
ROUTINE_NAME = the FORTRAN name of the routine (IN UPPER CASE LETTERS).
|
|
routine_name = the FORTRAN name of the routine (IN lower case LETTERS).
|
|
routine_type = the type of argument returned by C functions.
|
|
= BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING, VOID.
|
|
[Instead of VOID, FCALLSCSUBn is recommended.]
|
|
argtype_i = the type of argument passed to the FORTRAN routine and must be
|
|
consistent in the definition and prototyping of the routine
|
|
= BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG, SHORT, STRING.
|
|
For vectors, i.e. 1 dim. arrays use
|
|
= BYTEV, DOUBLEV, FLOATV, INTV, LOGICALV, LONGV, SHORTV, STRINGV.
|
|
For vectors of vectors, 2 dim. arrays use
|
|
= BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV.
|
|
For n-dim. arrays use
|
|
= BYTEV..nV's..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V,
|
|
LONGV..V, SHORTV..V.
|
|
For routines changing the values of an argument, the keyword is
|
|
prepended by a 'P'.
|
|
= PBYTE, PDOUBLE, PFLOAT, PINT, PLOGICAL, PLONG, PSHORT,
|
|
PSTRING, PNSTRING, PPSTRING, PSTRINGV.
|
|
For EXTERNAL procedures passed as arguments use
|
|
= ROUTINE.
|
|
For exceptional arguments which require no massaging to fit the
|
|
argument passing mechanisms use
|
|
= PVOID.
|
|
The argument is cast and passed as (void *).
|
|
|
|
|
|
Notes:
|
|
|
|
0. For Fortran calling C++ routines, C++ does NOT easily allow support for:
|
|
STRINGV.
|
|
BYTEVV, DOUBLEVV, FLOATVV, INTVV, LOGICALVV, LONGVV, SHORTVV.
|
|
BYTEV..V, DOUBLEV..V, FLOATV..V, INTV..V, LOGICALV..V, LONGV..V, SHORTV..V.
|
|
Though there are ways to get around this restriction,
|
|
the restriction is not serious since these types are unlikely to be used as
|
|
arguments for a C++ routine.
|
|
|
|
1. FCALLSCSUB/FUNn expect that the routine to be 'wrapped' has been properly
|
|
prototyped, or at least declared.
|
|
|
|
|
|
2. cfortran.h may be expanded to handle a new argument type not already among
|
|
the above.
|
|
|
|
|
|
3. <BYTE|DOUBLE|BYTE|DOUBLE|FLOAT|INT|LOGICAL|LONG|SHORT><V|VV|VVV|...>
|
|
|
|
cfortran.h encourages the exact specification of the type and dimension of
|
|
array parameters because it allows the C compiler to detect errors in the
|
|
arguments when declaring the routine using FCALLSCSUB/FUNn, assuming the
|
|
routine to be 'wrapped' has been properly prototyped.
|
|
|
|
cfortran.h does not strictly require the exact specification since the argument
|
|
is merely the address of the array and is passed on to the calling routine.
|
|
Any array parameter could be declared as PVOID, but this circumvents
|
|
C's compiletime ability to check the correctness of arguments and is therefore
|
|
discouraged.
|
|
|
|
Passing the address of these arguments implies that PBYTEV, PFLOATV, ... ,
|
|
PDOUBLEVV, ... don't exist in cfortran.h, since by default the routine and the
|
|
calling code share the same array, i.e. the same values at the same memory
|
|
location.
|
|
|
|
These comments do NOT apply to arrays of (P)STRINGV. For these parameters,
|
|
cfortran.h passes a massaged copy of the array to the routine. When the routine
|
|
returns, STRINGV ignores the copy, while PSTRINGV replaces the calling
|
|
code's original array with copy, which may have been modified by the called
|
|
routine.
|
|
|
|
|
|
4. (P(N))STRING arguments have any trailing blanks removed before being passed
|
|
to C, the same holds true for each element in (P)STRINGV. Space is malloc'd in
|
|
all cases big enough to hold the original string (elements) as well as C's
|
|
terminating '\0'. i.e. The useful size of the string (elements) is the same in
|
|
both languages. P(N)STRING(V) => the string (elements) will be copied from the
|
|
malloc'd space back into the FORTRAN bytes. If one of the two escape mechanisms
|
|
mentioned below for PNSTRING has been used, the copying back to FORTRAN is
|
|
obviously not relevant.
|
|
|
|
|
|
5. (PN)STRING's, [NOT PSTRING's nor (P)STRINGV's,] behavior may be overridden
|
|
in two cases. In both cases PNSTRING and STRING behave identically.
|
|
|
|
a) If a (PN)STRING argument's first 4 bytes are all the NUL character,
|
|
i.e. '\0\0\0\0' the NULL pointer is passed to the C routine.
|
|
|
|
b) If the characters of a (PN)STRING argument contain at least one HEX-00, i.e.
|
|
the NUL character, i.e. C strings' terminating '\0', the address of the string
|
|
is simply passed to the C routine. i.e. The argument is treated in this case as
|
|
it would be with PPSTRING, to which we refer the reader for more detail.
|
|
|
|
Mechanism a) overrides b). Therefore, to use this mechanism to pass the NULL
|
|
string, "", to C, the first character of the string must obviously be the NUL
|
|
character, but of the first 4 characters in the string, at least one must not
|
|
be HEX-00.
|
|
|
|
Example:
|
|
C FORTRAN /* C */
|
|
character*40 str #include "cfortran.h"
|
|
C Set up a NULL as : void cs(char *s) {if (s) printf("%s.\n",s);}
|
|
C i) 4 NUL characters. FCALLSCSUB1(cs,CS,cs,STRING)
|
|
C ii) NULL pointer.
|
|
character*4 NULL
|
|
NULL = CHAR(0)//CHAR(0)//CHAR(0)//CHAR(0)
|
|
|
|
data str/'just some string'/
|
|
|
|
C Passing the NULL pointer to cs.
|
|
call cs(NULL)
|
|
C Passing a copy of 'str' to cs.
|
|
call cs(str)
|
|
C Passing address of 'str' to cs. Trailing blanks NOT killed.
|
|
str(40:) = NULL
|
|
call cs(str)
|
|
end
|
|
|
|
Strings passed from Fortran to C via (PN)STRING must not have undefined
|
|
contents, otherwise undefined behavior will result, since one of the above two
|
|
escape mechanisms may occur depending on the contents of the string.
|
|
|
|
This is not be a problem for STRING arguments, which are read-only in the C
|
|
routine and hence must have a well defined value when being passed in.
|
|
|
|
PNSTRING arguments require special care. Even if they are write-only in the C
|
|
routine, PNSTRING's above two escape mechanisms require that the value of the
|
|
argument be well defined when being passed in from Fortran to C. Therefore,
|
|
unless one or both of PNSTRING's escape mechanisms are required, PSTRING should
|
|
be used instead of PNSTRING.
|
|
Prior to version 2.8, PSTRING did have the above two escape mechanisms,
|
|
but they were removed from PSTRING to allow strings with undefined contents to
|
|
be passed in. PNSTRING behaves like the old PSTRING.
|
|
[Thanks go to Paul Dubois (dubios@icf.llnl.gov) for pointing out that PSTRING
|
|
must allow for strings with undefined contents to be passed in.]
|
|
|
|
Example:
|
|
C FORTRAN /* C */
|
|
character*10 s,sn #include "cfortran.h"
|
|
void ps(char *s) {strcpy(s,"hello");}
|
|
C Can call ps with undef. s. FCALLSCSUB1(ps,PS,ps,PSTRING)
|
|
call ps(s) FCALLSCSUB1(ps,PNS,pns,PNSTRING)
|
|
print *,s,'=s'
|
|
|
|
C Can't call pns with undef. s.
|
|
C e.g. If first 4 bytes of s were
|
|
C "\0\0\0\0", ps would try
|
|
C to copy to NULL because
|
|
C of PNSTRING mechanism.
|
|
sn = ""
|
|
call pns(sn)
|
|
print *,sn,'=sn'
|
|
|
|
end
|
|
|
|
|
|
6. PPSTRING
|
|
The address of the string argument is simply passed to the C routine. Therefore
|
|
the C routine and the FORTRAN calling code share the same string at the same
|
|
memory location. If the C routine modifies the string, the string will also be
|
|
modified for the FORTRAN calling code.
|
|
The user is responsible for negociating the differences in representation of a
|
|
string in Fortran and in C, i.e. the differences are not automatically resolved
|
|
as they are for (P(N)STRING(V).
|
|
This mechanism is provided for two reasons:
|
|
- Some C routines require the string to exist at the given memory location,
|
|
after the C routine has exited. Recall that for the usual (P(N)STRING(V)
|
|
mechanism, a copy of the FORTRAN string is given to the C routine, and this
|
|
copy ceases to exist after returning to the FORTRAN calling code.
|
|
- This mechanism can save runtime CPU cycles over (P(N)STRING(V), since it
|
|
does not perform their malloc, copy and kill trailing blanks of the string
|
|
to be passed.
|
|
Only in a small minority of cases does the potential benefit of the saved
|
|
CPU cycles outweigh the programming effort required to manually resolve
|
|
the differences in representation of a string in Fortran and in C.
|
|
|
|
For arguments passed via PPSTRING, the argument passed may also be an array of
|
|
strings.
|
|
|
|
|
|
7. ROUTINE
|
|
ANSI C requires that the type of the value returned by the routine be known,
|
|
For all ROUTINE arguments passed from Fortran to C, the type of ROUTINE is
|
|
specified by defining a cast as follows:
|
|
|
|
#undef ROUTINE_j
|
|
#define ROUTINE_j (cast)
|
|
where:
|
|
j [1-n], is the argument being specifying.
|
|
(cast) is a cast matching that of the argument expected by the C
|
|
function protoytpe for which a wrapper is being defined.
|
|
|
|
e.g. To create a Fortran wrapper for qsort(3C):
|
|
#undef ROUTINE_4
|
|
#define ROUTINE_4 (int (*)(void *,void *))
|
|
FCALLSCSUB4(qsort,FQSORT,fqsort,PVOID,INT,INT,ROUTINE)
|
|
|
|
In order to maintain backward compatibility, cfortran.h defines a generic cast
|
|
for ROUTINE_1, ROUTINE_2, ..., ROUTINE_27. The user's definition is therefore
|
|
strictly required only for DEC C, which at the moment is the only compiler
|
|
which insists on the correct cast for pointers to functions.
|
|
|
|
When using the ROUTINE argument inside some Fortran code:
|
|
- it is difficult to pass a C routine as the parameter,
|
|
since in many Fortran implementations,
|
|
Fortran has no access to the normal C namespace.
|
|
e.g. For most UNIX,
|
|
Fortran implicitly only has access to C routines ending in _.
|
|
If the calling Fortran code receives the routine as a parameter
|
|
it can of course easily pass it along.
|
|
- if a Fortran routine is passed directly as the parameter,
|
|
the called C routine must call the parameter routine
|
|
using the Fortran argument passing conventions.
|
|
- if a Fortran routine is to be passed as the parameter,
|
|
but if Fortran can be made to pass a C routine as the parameter,
|
|
then it may be best to pass a C-callable wrapper for the Fortran routine.
|
|
The called C routine is thus spared all Fortran argument passing conventions.
|
|
cfortran.h can be used to create such a C-callable wrapper
|
|
to the parameter Fortran routine.
|
|
|
|
ONLY PowerStationFortran:
|
|
This Fortran provides no easy way to pass a Fortran routine as an argument to a
|
|
C routine. The problem arises because in Fortran the stack is cleared by the
|
|
called routine, while in C/C++ it is cleared by the caller.
|
|
The C/C++ stack clearing behavior can be changed to that of Fortran by using
|
|
stdcall__ in the function prototype. The stdcall__ cannot be applied in this
|
|
case since the called C routine expects the ROUTINE parameter to be a C routine
|
|
and does not know that it should apply stdcall__.
|
|
In principle the cfortran.h generated Fortran callable wrapper for the called C
|
|
routine should be able to massage the ROUTINE argument such that stdcall__ is
|
|
performed, but it is not yet known how this could be easily done.
|
|
|
|
|
|
8. THE FOLLOWING INSTRUCTIONS ARE NOT REQUIRED FOR VAX VMS
|
|
------------
|
|
(P)STRINGV information [NOT required for VAX VMS]: cfortran.h cannot convert
|
|
the FORTRAN vector of STRINGS to the required C vector of STRINGS without
|
|
explicitly knowing the number of elements in the vector. The application must
|
|
do one of the following for each (P)STRINGV argument in a routine before that
|
|
routine's FCALLSCFUNn/SUBn is called:
|
|
|
|
#define routine_name_STRV_Ai NUM_ELEMS(j)
|
|
or
|
|
#define routine_name_STRV_Ai NUM_ELEM_ARG(k)
|
|
or
|
|
#define routine_name_STRV_Ai TERM_CHARS(l,m)
|
|
|
|
where: routine_name is as above.
|
|
i [i=1->n.] specifies the argument number of a STRING VECTOR.
|
|
j would specify a fixed number of elements.
|
|
k [k=1->n. k!=i] would specify an integer argument which specifies the
|
|
number of elements.
|
|
l [char] the terminating character at the beginning of an
|
|
element, indicating to cfortran.h that the preceding
|
|
elements in the vector are the valid ones.
|
|
m [m=1-...] the number of terminating characters required to appear
|
|
at the beginning of the terminating string element.
|
|
The terminating element is NOT passed on to
|
|
the C routine.
|
|
|
|
e.g. #define ce_STRV_A1 TERM_CHARS(' ',2)
|
|
FCALLSCSUB1(ce,CE,ce,STRINGV)
|
|
|
|
cfortran.h will pass on all elements, in the 1st and only argument to the C
|
|
routine ce, of the STRING VECTOR until, but not including, the first string
|
|
element beginning with 2 blank, ' ', characters.
|
|
|
|
|
|
9. INSTRUCTIONS REQUIRED ONLY FOR FORTRAN COMPILERS WHICH GENERATE
|
|
-------------
|
|
ROUTINE NAMES WHICH ARE UNDISTINGUISHABLE FROM C ROUTINE NAMES
|
|
i.e. VAX VMS
|
|
AbsoftUNIXFortran (AbsoftProFortran ok, since it uses Uppercase names.)
|
|
HP9000 if not using the +ppu option of f77
|
|
IBM RS/6000 if not using the -qextname option of xlf
|
|
Call them the same_namespace compilers.
|
|
|
|
FCALLSCSUBn(...) and FCALLSCFUNn(...), when compiled, are expanded into
|
|
'wrapper' functions, so called because they wrap around the original C
|
|
functions and interface the format of the original C functions' arguments and
|
|
return values with the format of the FORTRAN call.
|
|
|
|
Ideally one wants to be able to call the C routine from FORTRAN using the same
|
|
name as the original C name. This is not a problem for FORTRAN compilers which
|
|
append an underscore, '_', to the names of routines, since the original C
|
|
routine has the name 'name', and the FORTRAN wrapper is called 'name_'.
|
|
Similarly, if the FORTRAN compiler generates upper case names for routines, the
|
|
original C routine 'name' can have a wrapper called 'NAME', [Assuming the C
|
|
routine name is not in upper case.] For these compilers, e.g. Mips, CRAY, IBM
|
|
RS/6000 'xlf -qextname', HP-UX 'f77 +ppu', the naming of the wrappers is done
|
|
automatically.
|
|
|
|
For same_namespace compilers things are not as simple, but cfortran.h tries to
|
|
provide tools and guidelines to minimize the costs involved in meeting their
|
|
constraints. The following two options can provide same_namespace compilers
|
|
with distinct names for the wrapper and the original C function.
|
|
|
|
These compilers are flagged by cfortran.h with the CF_SAME_NAMESPACE constant,
|
|
so that the change in the C name occurs only when required.
|
|
|
|
For the remainder of the discussion, routine names generated by FORTRAN
|
|
compilers are referred to in lower case, these names should be read as upper
|
|
case for the appropriate compilers.
|
|
|
|
|
|
HP9000: (When f77 +ppu is not used.)
|
|
f77 has a -U option which forces uppercase external names to be generated.
|
|
Unfortunately, cc does not handle recursive macros. Hence, if one wished to use
|
|
-U for separate C and FORTRAN namespaces, one would have to adopt a different
|
|
convention of naming the macros which allow C to call FORTRAN subroutines.
|
|
(Functions are not a problem.) The macros are currently the uppercase of the
|
|
original FORTRAN name, and would have to be changed to lower case or mixed
|
|
case, or to a different name. (Lower case would of course cause conflicts on
|
|
many other machines.) Therefore, it is suggested that f77 -U not be used, and
|
|
instead that Option a) or Option b) outlined below be used.
|
|
|
|
|
|
VAX/VMS:
|
|
For the name used by FORTRAN in calling a C routine to be the same as that of
|
|
the C routine, the source code of the C routine is required. A preprocessor
|
|
directive can then force the C compiler to generate a different name for the C
|
|
routine.
|
|
e.g. #if defined(vms)
|
|
#define name name_
|
|
#endif
|
|
void name() {printf("name: was called.\n");}
|
|
FCALLSCSUB0(name,NAME,name)
|
|
|
|
In the above, the C compiler generates the original routine with the name
|
|
'name_' and a wrapper called 'NAME'. This assumes that the name of the routine,
|
|
as seen by the C programmer, is not in upper case. The VAX VMS linker is not
|
|
case sensitive, allowing cfortran.h to export the upper case name as the
|
|
wrapper, which then doesn't conflict with the routine name in C. Since the IBM,
|
|
HP and AbsoftUNIXFortran platforms have case sensitive linkers
|
|
this technique is not available to them.
|
|
|
|
The above technique is required even if the C name is in mixed case, see
|
|
Option a) for the other compilers, but is obviously not required when
|
|
Option b) is used.
|
|
|
|
|
|
Option a) Mixed Case names for the C routines to be called by FORTRAN.
|
|
|
|
If the original C routines have mixed case names, there are no name space
|
|
conflicts.
|
|
|
|
Nevertheless for VAX/VMS, the technique outlined above must also used.
|
|
|
|
|
|
Option b) Modifying the names of C routines when used by FORTRAN:
|
|
|
|
The more robust naming mechanism, which guarantees portability to all machines,
|
|
'renames' C routines when called by FORTRAN. Indeed, one must change the names
|
|
on same_namespace compilers when FORTRAN calls C routines for which the source
|
|
is unavailable. [Even when the source is available, renaming may be preferable
|
|
to Option a) for large libraries of C routines.]
|
|
|
|
Obviously, if done for a single type of machine, it must be done for all
|
|
machines since the names of routines used in FORTRAN code cannot be easily
|
|
redefined for different machines.
|
|
|
|
The simplest way to achieve this end is to do explicitly give the modified
|
|
FORTRAN name in the FCALLSCSUBn(...) and FCALLSCFUNn(...) declarations. e.g.
|
|
|
|
FCALLSCSUB0(name,CFNAME,cfname)
|
|
|
|
This allows FORTRAN to call the C routine 'name' as 'cfname'. Any name can of
|
|
course be used for a given routine when it is called from FORTRAN, although
|
|
this is discouraged due to the confusion it is sure to cause. e.g. Bizarre,
|
|
but valid and allowing C's 'call_back' routine to be called from FORTRAN as
|
|
'abcd':
|
|
|
|
FCALLSCSUB0(call_back,ABCD,abcd)
|
|
|
|
|
|
cfortran.h also provides preprocessor directives for a systematic 'renaming' of
|
|
the C routines when they are called from FORTRAN. This is done by redefining
|
|
the fcallsc macro before the FCALLSCSUB/FUN/n declarations as follows:
|
|
|
|
#undef fcallsc
|
|
#define fcallsc(UN,LN) preface_fcallsc(CF,cf,UN,LN)
|
|
|
|
FCALLSCSUB0(hello,HELLO,hello)
|
|
|
|
Will cause C's routine 'hello' to be known in FORTRAN as 'cfhello'. Similarly
|
|
all subsequent FCALLSCSUB/FUN/n declarations will generate wrappers to allow
|
|
FORTRAN to call C with the C routine's name prefaced by 'cf'. The following has
|
|
the same effect, with subsequent FCALLSCSUB/FUN/n's appending the modifier to
|
|
the original C routines name.
|
|
|
|
#undef fcallsc
|
|
#define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN)
|
|
|
|
FCALLSCSUB0(Xroutine,ROUTINE,routine)
|
|
|
|
Hence, C's Xroutine is called from FORTRAN as:
|
|
CALL XROUTINEY()
|
|
|
|
The original behavior of FCALLSCSUB/FUN/n, where FORTRAN routine names are left
|
|
identical to those of C, is returned using:
|
|
|
|
#undef fcallsc
|
|
#define fcallsc(UN,LN) orig_fcallsc(UN,LN)
|
|
|
|
|
|
In C, when passing a C routine, i.e. its wrapper, as an argument to a FORTRAN
|
|
routine, the FORTRAN name declared is used and the correct fcallsc must be in
|
|
effect. E.g. Passing 'name' and 'routine' of the above examples to the FORTRAN
|
|
routines, FT1 and FT2, respectively:
|
|
|
|
/* This might not be needed if fcallsc is already orig_fcallsc. */
|
|
#undef fcallsc
|
|
#define fcallsc(UN,LN) orig_fcallsc(UN,LN)
|
|
FT1(C_FUNCTION(CFNAME,cfname));
|
|
|
|
#undef fcallsc
|
|
#define fcallsc(UN,LN) append_fcallsc(Y,y,UN,LN)
|
|
FT1(C_FUNCTION(XROUTINE,xroutine));
|
|
|
|
If the names of C routines are modified when used by FORTRAN, fcallsc would
|
|
usually be defined once in a header_file.h for the application. This definition
|
|
would then be used and be valid for the entire application and fcallsc would at
|
|
no point need to be redefined.
|
|
|
|
|
|
ONCE AGAIN: THE DEFINITIONS, INSTRUCTIONS, DECLARATIONS AND DIFFICULTIES
|
|
DESCRIBED HERE, NOTE 9. of II ii),
|
|
APPLY ONLY FOR VAX VMS,
|
|
IBM RS/6000 WITHOUT THE -qextname OPTION FOR xlf, OR
|
|
HP-UX WITHOUT THE +ppu OPTION FOR f77
|
|
AbsoftUNIXFortran
|
|
AND APPLY ONLY WHEN CREATING WRAPPERS WHICH ENABLE FORTRAN TO CALL C ROUTINES.
|
|
|
|
|
|
|
|
iii) Using C to manipulate FORTRAN COMMON BLOCKS:
|
|
-------------------------------------------------------
|
|
|
|
FORTRAN common blocks are set up with the following three constructs:
|
|
|
|
1.
|
|
#define Common_block_name COMMON_BLOCK(COMMON_BLOCK_NAME,common_block_name)
|
|
|
|
Common_block_name is in UPPER CASE.
|
|
COMMON_BLOCK_NAME is in UPPER CASE.
|
|
common_block_name is in lower case.
|
|
[Common_block_name actually follows the same 'rules' as Routine_name in Note 2.
|
|
of II i).] This construct exists to ensure that C code accessing the common
|
|
block is machine independent.
|
|
|
|
2.
|
|
COMMON_BLOCK_DEF(TYPEDEF_OF_STRUCT, Common_block_name);
|
|
|
|
where
|
|
typedef { ... } TYPEDEF_OF_STRUCT;
|
|
declares the structure which maps on to the common block. The #define of
|
|
Common_block_name must come before the use of COMMON_BLOCK_DEF.
|
|
|
|
3.
|
|
In exactly one of the C source files, storage should be set aside for the
|
|
common block with the definition:
|
|
|
|
TYPEDEF_OF_STRUCT Common_block_name;
|
|
|
|
The above definition may have to be omitted on some machines for a common block
|
|
which is initialized by Fortran BLOCK DATA or is declared with a smaller size
|
|
in the C routines than in the Fortran routines.
|
|
|
|
The rules for common blocks are not well defined when linking/loading a mixture
|
|
of C and Fortran, but the following information may help resolve problems.
|
|
|
|
From the 2nd or ANSI ed. of K&R C, p.31, last paragraph:
|
|
i)
|
|
An external variable must be defined, exactly once, outside of any function;
|
|
this sets aside storage for it.
|
|
ii)
|
|
The variable must also be declared in each function that wants to access it;
|
|
...
|
|
The declaration ... may be implicit from context.
|
|
|
|
In Fortran, every routine says 'common /bar/ foo',
|
|
i.e. part ii) of the above, but there's no part i) requirement.
|
|
cc/ld on some machines don't require i) either.
|
|
Therefore, when handling Fortran, and sometimes C,
|
|
the loader/linker must automagically set aside storage for common blocks.
|
|
|
|
Some loaders, including at least one for the CRAY, turn off the
|
|
'automagically set aside storage' capability for Fortran common blocks,
|
|
if any C object declares that common block.
|
|
Therefore, C code should define, i.e. set aside storage,
|
|
for the the common block as shown above.
|
|
|
|
e.g.
|
|
C Fortran
|
|
common /fcb/ v,w,x
|
|
character *(13) v, w(4), x(3,2)
|
|
|
|
/* C */
|
|
typedef struct { char v[13],w[4][13],x[2][3][13]; } FCB_DEF;
|
|
#define Fcb COMMON_BLOCK(FCB,fcb)
|
|
COMMON_BLOCK_DEF(FCB_DEF,Fcb);
|
|
FCB_DEF Fcb; /* Definition, which sets aside storage for Fcb, */
|
|
/* may appear in at most one C source file. */
|
|
|
|
|
|
C programs can place a string (or a multidimensional array of strings) into a
|
|
FORTRAN common block using the following call:
|
|
|
|
C2FCBSTR( CSTR, FSTR,DIMENSIONS);
|
|
|
|
where:
|
|
|
|
CSTR is a pointer to the first element of C's copy of the string (array).
|
|
The C code must use a duplicate of, not the original, common block string,
|
|
because the FORTRAN common block does not allocate space for C strings'
|
|
terminating '\0'.
|
|
|
|
FSTR is a pointer to the first element of the string (array) in the common
|
|
block.
|
|
|
|
DIMENSIONS is the number of dimensions of string array.
|
|
e.g. char a[10] has DIMENSIONS=0.
|
|
char aa[10][17] has DIMENSIONS=1.
|
|
etc...
|
|
|
|
C2FCBSTR will copy the string (array) from CSTR to FSTR, padding with blanks,
|
|
' ', the trailing characters as required. C2FCBSTR uses DIMENSIONS and FSTR to
|
|
determine the lengths of the individual string elements and the total number of
|
|
elements in the string array.
|
|
|
|
Note that:
|
|
- the number of string elements in CSTR and FSTR are identical.
|
|
- for arrays of strings, the useful lengths of strings in CSTR and FSTR must be
|
|
the same. i.e. CSTR elements each have 1 extra character to accommodate the
|
|
terminating '\0'.
|
|
- On most non-ANSI compilers, the DIMENSION argument cannot be prepended by any
|
|
blanks.
|
|
|
|
|
|
FCB2CSTR( FSTR, CSTR,DIMENSIONS)
|
|
|
|
is the inverse of C2FCBSTR, and shares the same arguments and caveats.
|
|
FCB2CSTR copies each string element of FSTR to CSTR, minus FORTRAN strings'
|
|
trailing blanks.
|
|
|
|
|
|
cfortran.h USERS ARE STRONGLY URGED TO EXAMINE THE COMMON BLOCK EXAMPLES IN
|
|
cfortest.c AND cfortex.f. The use of strings in common blocks is
|
|
demonstrated, along with a suggested way for C to imitate FORTRAN EQUIVALENCE'd
|
|
variables.
|
|
|
|
|
|
===> USERS OF CFORTRAN.H NEED READ NO FURTHER <===
|
|
|
|
|
|
III Some Musings
|
|
----------------
|
|
|
|
cfortran.h is simple enough to be used by the most basic of applications, i.e.
|
|
making a single C/FORTRAN routine available to the FORTRAN/C programmers. Yet
|
|
cfortran.h is powerful enough to easily make entire C/FORTRAN libraries
|
|
available to FORTRAN/C programmers.
|
|
|
|
|
|
cfortran.h is the ideal tool for FORTRAN libraries which are being (re)written
|
|
in C, but are to (continue to) support FORTRAN users. It allows the routines to
|
|
be written in 'natural C', without having to consider the FORTRAN argument
|
|
passing mechanisms of any machine. It also allows C code accessing these
|
|
rewritten routines, to use the C entry point. Without cfortran.h, one risks the
|
|
perverse practice of C code calling a C function using FORTRAN argument passing
|
|
mechanisms!
|
|
|
|
|
|
Perhaps the philosophy and mechanisms of cfortran.h could be used and extended
|
|
to create other language bridges such as ADAFORTRAN, CPASCAL, COCCAM, etc.
|
|
|
|
|
|
The code generation machinery inside cfortran.h, i.e. the global structure is
|
|
quite good, being clean and workable as seen by its ability to meet the needs
|
|
and constraints of many different compilers. Though the individual instructions
|
|
of the A..., C..., T..., R... and K... tables deserve to be cleaned up.
|
|
|
|
|
|
|
|
IV Getting Serious with cfortran.h
|
|
-----------------------------------
|
|
|
|
cfortran.h is set up to be as simple as possible for the casual user. While
|
|
this ease of use will always be present, 'hooks', i.e. preprocessor directives,
|
|
are required in cfortran.h so that some of the following 'inefficiencies' can
|
|
be eliminated if they cause difficulties:
|
|
|
|
o cfortran.h contains a few small routines for string manipulation. These
|
|
routines are declared static and are included and compiled in all source code
|
|
which uses cfortran.h. Hooks should be provided in cfortran.h to create an
|
|
object file of these routines, allowing cfortran.h to merely prototypes
|
|
these routines in the application source code. This is the only 'problem' which
|
|
afflicts both halves of cfortran.h. The remaining discussion refers to the C
|
|
calls FORTRAN half only.
|
|
|
|
o Similar to the above routines, cfortran.h generates code for a 'wrapper'
|
|
routine for each FUNCTION exported from FORTRAN. Again cfortran.h needs
|
|
preprocessor directives to create a single object file of these routines,
|
|
and to merely prototype them in the applications.
|
|
|
|
o Libraries often contain hundreds of routines. While the preprocessor makes
|
|
quick work of generating the required interface code from cfortran.h and the
|
|
application.h's, it may be convenient for very large stable libraries to have
|
|
final_application.h's which already contain the interface code, i.e. these
|
|
final_application.h's would not require cfortran.h. [The convenience can be
|
|
imagined for the VAX VMS CC compiler which has a fixed amount of memory for
|
|
preprocessor directives. Not requiring cfortran.h, with its hundreds of
|
|
directives, could help prevent this compiler from choking on its internal
|
|
limits quite so often.]
|
|
|
|
With a similar goal in mind, cfortran.h defines 100's of preprocessor
|
|
directives. There is always the potential that these will clash with other tags
|
|
in the users code, so final_applications.h, which don't require cfortran.h,
|
|
also provide the solution.
|
|
|
|
In the same vein, routines with more than 14 arguments can not be interfaced by
|
|
cfortran.h with compilers which limit C macros to 31 arguments. To resolve this
|
|
difficulty, final_application.h's can be created on a compiler without this
|
|
limitation.
|
|
|
|
Therefore, new machinery is required to do:
|
|
|
|
application.h + cfortran.h => final_application.h
|
|
|
|
The following example may help clarify the means and ends:
|
|
|
|
If the following definition of the HBOOK1 routine, the /*commented_out_part*/,
|
|
is passed through the preprocessor [perhaps #undefing and #defining preprocessor
|
|
constants if creating an application.h for compiler other than that of the
|
|
preprocessor being used, e.g. cpp -Umips -DCRAY ... ] :
|
|
|
|
#include "cfortran.h"
|
|
PROTOCCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT)
|
|
/*#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \*/
|
|
CCALLSFSUB6(HBOOK1,hbook1,INT,STRING,INT,FLOAT,FLOAT,FLOAT, \
|
|
ID,CHTITLE,NX,XMI,XMA,VMX)
|
|
|
|
A function prototype is produced by the PROTOCCALLSFSUB6(...).
|
|
Interface code is produced, based on the 'variables',
|
|
ID,CHTITLE,NX,XMI,XMA,VMX, which will correctly massage a HBOOK1 call.
|
|
Therefore, adding the #define line:
|
|
|
|
'prototype code'
|
|
#define HBOOK1(ID,CHTITLE,NX,XMI,XMA,VMX) \
|
|
'interface code'(ID,CHTITLE,NX,XMI,XMA,VMX)
|
|
|
|
which is placed into final_application.h.
|
|
|
|
The only known limitation of the above method does not allow the 'variable'
|
|
names to include B1,B2,...,B9,BA,BB,...
|
|
|
|
Obviously the machinery to automatically generate final_applications.h from
|
|
cfortran.h and applications.h needs more than just some preprocessor
|
|
directives, but a fairly simple unix shell script should be sufficient. Any
|
|
takers?
|
|
|
|
|
|
|
|
V Machine Dependencies of cfortran.h
|
|
------------------------------------
|
|
|
|
Porting cfortran.h applications, e.g. the hbook.h and cstring.c mentioned
|
|
above, to other machines is trivial since they are machine independent. Porting
|
|
cfortran.h requires a solid knowledge of the new machines C preprocessor, and
|
|
its FORTRAN argument passing mechanisms. Logically cfortran.h exists as two
|
|
halves, a "C CALLS FORTRAN" and a "FORTRAN CALLS C" utility. In some cases it
|
|
may be perfectly reasonable to port only 'one half' of cfortran.h onto a new
|
|
system.
|
|
|
|
|
|
The lucky programmer porting cfortran.h to a new machine, must discover the
|
|
FORTRAN argument passing mechanisms. A safe starting point is to assume that
|
|
variables and arrays are simply passed by reference, but nothing is guaranteed.
|
|
Strings, and n-dimensional arrays of strings are a different story. It is
|
|
doubtful that any systems do it quite like VAX VMS does it, so that a UNIX or
|
|
f2c versions may provide an easier starting point.
|
|
|
|
|
|
cfortran.h uses and abuses the preprocessor's ## operator. Although the ##
|
|
operator does not exist in many compilers, many kludges do. cfortran.h uses
|
|
/**/ with no space allowed between the slashes, '/', and the macros or tags
|
|
to be concatenated. e.g.
|
|
#define concat(a,b) a/**/b /* works*/
|
|
main()
|
|
{
|
|
concat(pri,ntf)("hello"); /* e.g. */
|
|
}
|
|
N.B. On some compilers without ##, /**/ may also not work. The author may be
|
|
able to offer alternate kludges.
|
|
|
|
|
|
|
|
VI Bugs in vendors C compilers and other curiosities
|
|
----------------------------------------------------
|
|
|
|
1. ULTRIX xxxxxx 4.3 1 RISC
|
|
|
|
Condolences to long suffering ultrix users!
|
|
DEC supplies a working C front end for alpha/OSF, but not for ultrix.
|
|
|
|
From K&R ANSI C p. 231:
|
|
ultrix> cat cat.c
|
|
#define cat(x, y) x ## y
|
|
#define xcat(x,y) cat(x,y)
|
|
cat(cat(1,2),3)
|
|
xcat(xcat(1,2),3)
|
|
ultrix> cc -E cat.c
|
|
123 <---- Should be: cat(1,2)3
|
|
123 <---- Correct.
|
|
ultrix>
|
|
|
|
The problem for cfortran.h, preventing use of -std and -std1:
|
|
ultrix> cat c.c
|
|
#define cat(x, y) x ## y
|
|
#define xcat(x,y) cat(x,y)
|
|
#define AB(X) X+X
|
|
#define C(E,F,G) cat(E,F)(G)
|
|
#define X(E,F,G) xcat(E,F)(G)
|
|
C(A,B,2)
|
|
X(A,B,2)
|
|
ultrix> cc -std1 -E c.c
|
|
2+2
|
|
AB (2) <---- ?????????????
|
|
ultrix>
|
|
ultrix> cc -std0 -E c.c
|
|
2+2
|
|
AB(2) <---- ?????????????
|
|
ultrix>
|
|
|
|
Due to further ultrix preprocessor problems,
|
|
for all definitions of definitions with arguments,
|
|
cfortran.h >= 3.0 includes the arguments and recommends the same,
|
|
even though it is not required by ANSI C.
|
|
e.g. Users are advised to do
|
|
#define fcallsc(UN,LN) orig_fcallsc(UN,LN)
|
|
instead of
|
|
#define fcallsc orig_fcallsc
|
|
since ultrix fails to properly preprocess the latter example.
|
|
CRAY used to (still does?) occasionally trip up on this problem.
|
|
|
|
|
|
2. ConvexOS convex C210 11.0 convex
|
|
|
|
In a program with a C main, output to LUN=6=* from Fortran goes into
|
|
$pwd/fort.6 instead of stdout. Presumably, a magic incantation can be called
|
|
from the C main in order to properly initialize the Fortran I/O.
|
|
|
|
|
|
3. SunOS 5.3 Generic_101318-69 sun4m sparc
|
|
|
|
The default data and code alignments produced by cc, gcc and f77 are compatible.
|
|
If deviating from the defaults, consistent alignment options must be used
|
|
across all objects compiled by cc and f77. [Does gcc provide such options?]
|
|
|
|
|
|
4. SunOS 5.3 Generic_101318-69 sun4m sparc with cc: SC3.0.1 13 Jul 1994
|
|
or equivalently
|
|
ULTRIX 4.4 0 RISC using cc -oldc
|
|
are K&R C preprocessors that suffer from infinite loop macros, e.g.
|
|
|
|
zedy03> cat src.c
|
|
#include "cfortran.h"
|
|
PROTOCCALLSFFUN1(INT,FREV,frev, INTV)
|
|
#define FREV(A1) CCALLSFFUN1( FREV,frev, INTV, A1)
|
|
/* To avoid the problem, deletete these ---^^^^--- spaces. */
|
|
main() { static int a[] = {1,2}; FREV(a); return EXIT_SUCCESS; }
|
|
|
|
zedy03> cc -c -Xs -v -DMAX_PREPRO_ARGS=31 -D__CF__KnR src.c
|
|
"src.c", line 4: FREV: actuals too long
|
|
"src.c", line 4: FREV: actuals too long
|
|
.... 3427 more lines of the same message
|
|
"src.c", line 4: FREV: actuals too long
|
|
cc : Fatal error in /usr/ccs/lib/cpp
|
|
Segmentation fault (core dumped)
|
|
|
|
|
|
5. Older sun C compilers
|
|
|
|
To link to f77 objects, older sun C compilers require the math.h macros:
|
|
|
|
#define RETURNFLOAT(x) { union {double _d; float _f; } _kluge; \
|
|
_kluge._f = (x); return _kluge._d; }
|
|
#define ASSIGNFLOAT(x,y) { union {double _d; float _f; } _kluge; \
|
|
_kluge._d = (y); x = _kluge._f; }
|
|
|
|
Unfortunately, in at least some copies of the sun math.h, the semi-colon
|
|
for 'float _f;' is left out, leading to compiler warnings.
|
|
|
|
The solution is to correct math.h, or to change cfortran.h to #define
|
|
RETURNFLOAT(x) and ASSIGNFLOAT(x,y) instead of including math.h.
|
|
|
|
|
|
6. gcc version 2.6.3 and probably all other versions as well
|
|
|
|
Unlike all other C compilers supported by cfortran.h,
|
|
'gcc -traditional' promotes to double all functions returning float
|
|
as demonstrated bu the following example.
|
|
|
|
/* m.c */
|
|
#include <stdio.h>
|
|
int main() { FLOAT_FUNCTION d(); float f; f = d(); printf("%f\n",f); return 0; }
|
|
|
|
/* d.c */
|
|
float d() { return -123.124; }
|
|
|
|
burow[29] gcc -c -traditional d.c
|
|
burow[30] gcc -DFLOAT_FUNCTION=float m.c d.o && a.out
|
|
0.000000
|
|
burow[31] gcc -DFLOAT_FUNCTION=double m.c d.o && a.out
|
|
-123.124001
|
|
burow[32]
|
|
|
|
Thus, 'gcc -traditional' is not supported by cfortran.h.
|
|
Support would require the same RETURNFLOAT, etc. macro machinery
|
|
present in old sun math.h, before sun gave up the same promotion.
|
|
|
|
|
|
7. CRAY
|
|
|
|
At least some versions of the t3e and t3d C preprocessor are broken
|
|
in the fashion described below.
|
|
At least some versions of the t90 C preprocessor do not have this problem.
|
|
|
|
On the CRAY, all Fortran names are converted to uppercase.
|
|
Generally the uppercase name is also used for the macro interface
|
|
created by cfortran.h.
|
|
|
|
For example, in the following interface,
|
|
EASY is both the name of the macro in the original C code
|
|
and EASY is the name of the resulting function to be called.
|
|
|
|
#define EASY(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B)
|
|
|
|
The fact that a macro called EASY() expands to a function called EASY()
|
|
is not a problem for a working C preprocessor.
|
|
From Kernighan and Ritchie, 2nd edition, p.230:
|
|
|
|
In both kinds of macro, the replacement token sequence is repeatedly
|
|
rescanned for more identifiers. However, once a given identifier has been
|
|
replaced in a given expansion, it is not replaced if it turns up again during
|
|
rescanning; instead it is left unchanged.
|
|
|
|
Unfortunately, some CRAY preprocessors are broken and don't obey the above rule.
|
|
A work-around is for the user to NOT use the uppercase name
|
|
of the name of the macro interface provided by cfortran.h. For example:
|
|
|
|
#define Easy(A,B) CCALLSFSUB2(EASY,easy, PINT, INTV, A, B)
|
|
|
|
Luckily, the above work-around is not required since the following
|
|
work-around within cfortran.h also circumvents the bug:
|
|
|
|
/* (UN), not UN, is required in order to get around CRAY preprocessor bug.*/
|
|
#define CFC_(UN,LN) (UN) /* Uppercase FORTRAN symbols. */
|
|
|
|
Aside: The Visual C++ compiler is happy with UN, but barfs on (UN),
|
|
so either (UN) causes nonstandard C/C++ or Visual C++ is broken.
|
|
|
|
|
|
VII History and Acknowledgements
|
|
--------------------------------
|
|
|
|
1.0 - Supports VAX VMS using C 3.1 and FORTRAN 5.4. Oct. '90.
|
|
1.0 - Supports Silicon Graphics w. Mips Computer 2.0 f77 and cc. Feb. '91.
|
|
[Port of C calls FORTRAN half only.]
|
|
1.1 - Supports Mips Computer System 2.0 f77 and cc. Mar. '91.
|
|
[Runs on at least: Silicon Graphics IRIX 3.3.1
|
|
DECstations with Ultrix V4.1]
|
|
1.2 - Internals made simpler, smaller, faster, stronger. May '91.
|
|
- Mips version works on IBM RS/6000, this is now called the unix version.
|
|
1.3 - UNIX and VAX VMS versions are merged into a single cfortran.h. July '91.
|
|
- C can help manipulate (arrays of) strings in FORTRAN common blocks.
|
|
- Dimensions of string arrays arguments can be explicit.
|
|
- Supports Apollo DomainOS 10.2 (sys5.3) with f77 10.7 and cc 6.7.
|
|
|
|
2.0 - Improved code generation machinery creates K&R or ANSI C. Aug. '91.
|
|
- Supports Sun, CRAY. f2c with vcc on VAX Ultrix.
|
|
- cfortran.h macros now require routine and COMMON block names in both
|
|
upper and lower case. No changes required to applications though.
|
|
- PROTOCCALLSFSUBn is eliminated, with no loss to cfortran.h performance.
|
|
- Improved tools and guidelines for naming C routines called by FORTRAN.
|
|
2.1 - LOGICAL correctly supported across all machines. Oct. '91.
|
|
- Improved support for DOUBLE PRECISION on the CRAY.
|
|
- HP9000 fully supported.
|
|
- VAX Ultrix cc or gcc with f77 now supported.
|
|
2.2 - SHORT, i.e. INTEGER*2, and BYTE now supported. Dec. '91.
|
|
- LOGICAL_STRICT introduced. More compact and robust internal tables.
|
|
- typeV and typeVV for type = BYTE, DOUBLE, FLOAT, INT, LOGICAL, LONG,SHORT.
|
|
- FORTRAN passing strings and NULL pointer to C routines improved.
|
|
2.3 - Extraneous arguments removed from many internal tables. May '92.
|
|
- Introduce pseudo argument type SIMPLE for user defined types.
|
|
- LynxOS using f2c supported. (Tested with LynxOS 2.0 386/AT.)
|
|
2.4 - Separation of internal C and Fortran compilation directives. Oct. '92.
|
|
- f2c and NAG f90 supported on all machines.
|
|
2.5 - Minor mod.s to source and/or doc for HP9000, f2c, and NAG f90. Nov. '92.
|
|
2.6 - Support external procedures as arguments with type ROUTINE. Dec. '92.
|
|
2.7 - Support Alpha VMS. Support HP9000 f77 +ppu Jan. '93.
|
|
- Support arrays with up to 7 dimensions.
|
|
- Minor mod. of Fortran NULL to C via (P)STRING.
|
|
- Specify the type of ROUTINE passed from Fortran to C [ANSI C requirement.]
|
|
- Macros never receive a null parameter [RS/6000 requirement.]
|
|
2.8 - PSTRING for Fortran calls C no longer provides escape to pass April'93.
|
|
NULL pointer nor to pass address of original string.
|
|
PNSTRING introduced with old PSTRING's behavior.
|
|
PPSTRING introduced to always pass original address of string.
|
|
- Support Alpha/OSF.
|
|
- Document that common blocks used in C should be declared AND defined.
|
|
|
|
3.0 - Automagic handling of ANSI ## versus K&R /**/ preprocessor op. March'95.
|
|
- Less chance of name space collisions between cfortran.h and other codes.
|
|
- SIMPLE macros, supporting user defined types, have changed names.
|
|
3.1 - Internal macro name _INT not used. Conflicted with IRIX 5.3. May '95.
|
|
- SunOS, all versions, should work out of the box.
|
|
- ZTRINGV_ARGS|F(k) may no longer point to a PDOUBLE or PFLOAT argument.
|
|
- ConvexOS 11.0 supported.
|
|
3.2 - __hpux no longer needs to be restricted to MAX_PREPRO_ARGS=31. Oct. '95.
|
|
- PSTRING bug fixed.
|
|
- ZTRINGV_ARGS|F(k) may not point to a PBYTE,PINT,PLONG or PSHORT argument.
|
|
- (P)ZTRINGV machinery improved. Should lead to fewer compiler warnings.
|
|
(P)ZTRINGV no longer limits recursion or the nesting of routines.
|
|
- SIMPLE macros, supporting user defined types, have changed slightly.
|
|
3.3 - Supports PowerStation Fortran with Visual C++. Nov. '95.
|
|
- g77 should work using f2cFortran, though no changes made for it.
|
|
- (PROTO)CCALLSFFUN10 extended to (PROTO)CCALLSFFUN14.
|
|
- FCALLSCFUN10 and SUB10 extended to FCALLSCFUN14 and SUB14.
|
|
3.4 - C++ supported, Dec. '95.
|
|
but it required the reintroduction of PROTOCCALLSFSUBn for users.
|
|
- HP-UX f77 +800 supported.
|
|
3.5 - Absoft UNIX Fortran supported. Sept.'96.
|
|
3.6 - Minor corrections to cfortran.doc. Oct. '96.
|
|
- Fixed bug for 15th argument. [Thanks to Tom Epperly at Aspen Tech.]
|
|
- For AbsoftUNIXFortran, obey default of prepending _C to COMMON BLOCK name.
|
|
- Fortran calling C with ROUTINE argument fixed and cleaned up.
|
|
3.7 - Circumvent IBM and HP "null argument" preprocessor warning. Oct. '96
|
|
3.8 - (P)STRINGV and (P)ZTRINGV can pass a 1- or 2-dim. char array. Feb. '97
|
|
(P)ZTRINGV thus effectively also provides (P)ZTRING.
|
|
- (P)ZTRINGV accepts a (char *) pointer.
|
|
3.9 - Bug fixed for *VVVVV. May '97
|
|
- f2c: Work-around for strange underscore-dependent naming feature.
|
|
- NEC SX-4 supported.
|
|
- CRAY: LOGICAL conversion uses _btol and _ltob from CRAY's fortran.h.
|
|
- CRAY: Avoid bug of some versions of the C preprocessor.
|
|
- CRAY T3E: FORTRAN_REAL introduced.
|
|
|
|
4.0 - new/delete now used for C++. malloc/free still used for C. Jan. '98
|
|
- FALSE no longer is defined by cfortran.h .
|
|
- Absoft Pro Fortran for MacOS supported.
|
|
4.1 - COMMA and COLON no longer are defined by cfortran.h . April'98
|
|
- Bug fixed when 10th arg. or beyond is a string.
|
|
[Rob Lucchesi of NASA-Goddard pointed out this bug.]
|
|
- CCALLSFSUB/FUN extended from 14 to 27 arguments.
|
|
- Workaround SunOS CC 4.2 cast bug. [Thanks to Savrak SAR of CERN.]
|
|
4.2 - Portland Group needs -DpgiFortran . [Thank George Lai of NASA.] June '98
|
|
4.3 - (PROTO)CCALLSFSUB extended from 20 to 27 arguments. July '98
|
|
|
|
|
|
['Support' implies these and more recent releases of the respective
|
|
OS/compilers/linkers can be used with cfortran.h.
|
|
Earlier releases may also work.]
|
|
|
|
|
|
Acknowledgements:
|
|
- CERN very generously sponsored a week in 1994 for me to work on cfortran.h.
|
|
- M.L.Luvisetto (Istituto Nazionale Fisica Nucleare - Centro Nazionale
|
|
Analisi Fotogrammi, Bologna, Italy) provided all the support for the port to
|
|
the CRAY. Marisa's encouragement and enthusiasm was also much appreciated.
|
|
- J.Bunn (CERN) supported the port to PowerStation Fortran with Visual C++.
|
|
- Paul Schenk (UC Riverside, CERN PPE/OPAL) in June 1993 extended cfortran.h 2.7
|
|
to have C++ call Fortran. This was the starting point for full C++ in 3.4.
|
|
- Glenn P.Davis of University Corp. for Atmospheric Research (UCAR) / Unidata
|
|
supported the NEC SX-4 port and helped understand the CRAY.
|
|
- Tony Goelz of Absoft Corporation ported cfortran.h to Absoft.
|
|
- Though cfortran.h has been created in my 'copious' free time, I thank
|
|
NSERC for their generous support of my grad. student and postdoc years.
|
|
- Univ.Toronto, DESY, CERN and others have provided time on their computers.
|
|
|
|
|
|
THIS PACKAGE, I.E. CFORTRAN.H, THIS DOCUMENT, AND THE CFORTRAN.H EXAMPLE
|
|
PROGRAMS ARE PROPERTY OF THE AUTHOR WHO RESERVES ALL RIGHTS. THIS PACKAGE AND
|
|
THE CODE IT PRODUCES MAY BE FREELY DISTRIBUTED WITHOUT FEES, SUBJECT TO THE
|
|
FOLLOWING RESTRICTIONS:
|
|
- YOU MUST ACCOMPANY ANY COPIES OR DISTRIBUTION WITH THIS (UNALTERED) NOTICE.
|
|
- YOU MAY NOT RECEIVE MONEY FOR THE DISTRIBUTION OR FOR ITS MEDIA
|
|
(E.G. TAPE, DISK, COMPUTER, PAPER.)
|
|
- YOU MAY NOT PREVENT OTHERS FROM COPYING IT FREELY.
|
|
- YOU MAY NOT DISTRIBUTE MODIFIED VERSIONS WITHOUT CLEARLY DOCUMENTING YOUR
|
|
CHANGES AND NOTIFYING THE AUTHOR.
|
|
- YOU MAY NOT MISREPRESENTED THE ORIGIN OF THIS SOFTWARE, EITHER BY EXPLICIT
|
|
CLAIM OR BY OMISSION.
|
|
|
|
THE INTENT OF THE ABOVE TERMS IS TO ENSURE THAT THE CFORTRAN.H PACKAGE NOT BE
|
|
USED FOR PROFIT MAKING ACTIVITIES UNLESS SOME ROYALTY ARRANGEMENT IS ENTERED
|
|
INTO WITH ITS AUTHOR.
|
|
|
|
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
EXPRESSED OR IMPLIED. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
|
SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST
|
|
OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. THE AUTHOR IS NOT RESPONSIBLE
|
|
FOR ANY SUPPORT OR SERVICE OF THE CFORTRAN.H PACKAGE.
|
|
|
|
Burkhard Burow
|
|
burow@desy.de
|
|
|
|
P.S. Your comments and questions are welcomed and usually promptly answered.
|
|
|
|
VAX VMS and Ultrix, Alpha, OSF, Silicon Graphics (SGI), DECstation, Mips RISC,
|
|
Sun, CRAY, Convex, IBM RS/6000, Apollo DomainOS, HP, LynxOS, f2c, NAG, Absoft,
|
|
NEC SX-4, PowerStation and Visual C++ are registered trademarks of their
|
|
respective owners.
|
|
|
|
/* end: cfortran.doc */
|