Title: Mixed Language Programming on Seaborg
1Mixed Language Programming on Seaborg
- Mark Durst
- NERSC User Services
2Overview
- Matching variable types
- Mixing C and FORTRAN
- Mixing C and FORTRAN
- Mixing C and FORTRAN modules
- Character arguments
- Mixed-case names
- Other issues
- Mixed-language library use
- Further References
3Type Correspondences
FORTRAN C/C Bytes
REAL, REAL4, REAL(KIND4) float 4
REAL8, REAL(KIND8), DOUBLE PRECISION double 8
REAL16, REAL(KIND16) long double (with -qlongdouble) 16
INTEGER4, INTEGER(KIND4) int, long int 4
INTEGER8, INTEGER(KIND8) long long int (may require qlonglong) 8
INTEGER2 short int 2
COMPLEX, COMPLEX4 structure of two floats 8
COMPLEX8 structure of two doubles 16
DOUBLE COMPLEX, COMPLEX16 structure of two long doubles 32
CHARACTER Here be dragons
4Calling C from FORTRAN
- Calling by reference expected by FORTRAN
- Lowercase C routine name easiest (since Fortran
by default not case-sensitive) - No change in routine name
- qextname option to xlf and brename option to ld
provide other options
5Calling C from FORTRAN (example)
- !FILENAME f_main.f
- !
- PROGRAM f_calls_c
- IMPLICIT NONE
- REAL p1_x, p1_y, p2_x, p2_y
- EXTERNAL calc_dist
- p1_x 0.0
- p1_y 0.0
- p2_x 3.0
- p2_y 4.0
- CALL calc_dist(p1_x,p1_y,p2_x,p2_y)
- END PROGRAM f_calls_c
- / FILENAME calc_c.c
- /
- include ltmath.hgt
- void calc_dist(float x1, float y1, float x2,
float y2) -
- float dxsq, dysq, distance
- dxsq (x2-x1)(x2-x1)
- dysq (y2-y1)(y2-y1)
- distance sqrt( dxsq dysq )
- printf("The distance between the points is
13.5e\n", - distance)
6Calling C from FORTRAN (running)
- gt cc -c calc_c.c
- gt xlf90 -o f_calls_c f_main.f calc_c.o
- f_calls_c End of Compilation 1
- 1501-510 Compilation successful for file
f_main.f. - gt ./f_calls_c
- The distance between the points is 5.00000e00
7Calling FORTRAN from C
- Again, calling by reference most straightforward
- Must specify lxlf90 lm in cc command
- Or use xlf90 to load
8Calling FORTRAN from C (example)
- / FILENAME c_main.c
- Shows how to call a FORTRAN routine from C
- /
- extern void calc_dist(float, float, float,
float) - void main()
-
- float p1_x,p1_y,p2_x,p2_y
- p1_x 0.0
- p1_y 0.0
- p2_x 3.0
- p2_y 4.0
- calc_dist(p1_x,p1_y,p2_x,p2_y)
- ! FILENAME calc_f.f
- !
- SUBROUTINE calc_dist(x1,y1,x2,y2)
- IMPLICIT NONE
- REAL x1,y1,x2,y2
- REAL distance
- distance SQRT( (x2-x1)2 (y2-y1)2 )
- WRITE(6,1) distance
- 1 FORMAT("The distance between the points is ",
1pe13.5) - END SUBROUTINE calc_dist
9Calling FORTRAN from C (running)
- gt xlf90 -c calc_f.f
- calc_dist End of Compilation 1
- 1501-510 Compilation successful for file
calc_f.f. - gt cc -o c_calls_f c_main.c calc_f.o -lxlf90 -lm
- gt ./c_calls_f
- The distance between the points is 5.00000E00
10Calling C from FORTRAN
- Must have C wrapper function
- C compiler mangles routine names
- C wrapper name handled just like C
- Also any C that is just like C
- xlC command must be used to link
11Calling C from FORTRAN (C code)
- / FILENAME calc_c.h
- This is the C routine.
- /
- include ltiostream.hgt
- include ltmath.hgt
- templateltclass Tgt class calc
- public
- calc() cout ltlt"Inside C constructor"ltltendl
- calc() cout ltlt"Inside C destructor"ltltendl
-
-
- void calc_dist(T x1, T y1, T x2, T y2)
-
- T dxsq, dysq, distance
- dxsq (x2-x1)(x2-x1)
- dysq (y2-y1)(y2-y1)
- distance sqrt( dxsq dysq )
- cout ltlt"The distance between the points
is " - ltltdistanceltlt" \n"ltltendl
-
12Calling C from FORTRAN (C wrapper)
- / Filename calc_cwrapper.C /
- include ltstdio.hgt
- include "calc_c.h"
- extern "C" void calc_dist(float x,float y,float
X,float Y) - void calc_dist(float x,float y,float X,float
Y) - printf("Inside C function, creating C
object\n") - calcltfloatgt cnew calcltfloatgt()
- c-gtcalc_dist(x,y,X,Y)
-
- printf("Back in C function, will delete
C object\n") - delete c
13Calling C from FORTRAN (running)
- gt xlf90 -c f_main.f
- f_calls_c End of Compilation 1
- 1501-510 Compilation successful for file
f_main.f. - gt xlC -c calc_cwrapper.C
- gt xlC -o f_calls_c calc_cwrapper.o f_main.o -lm
-lxlf90 - gt ./f_calls_c
- Inside C function, creating C object
- Inside C constructor
- The distance between the points is 5
-
- Back in C function, will delete C object
- Inside C destructor
14Calling FORTRAN from C
- Can simply declare FORTRAN subroutine like C
- extern "C" void fortran_routine_name
- Or with FORTRAN function
- extern "C" return_type fortran_routine_name
15Calling F90 module routines from C
- Refer to FORTRAN routine as __modulename_MOD_routi
nename - There is apparently a way for C to read prototype
info out of .mod files
16Calling F90 module routines from C (module code)
- ! FILENAME calc_mod_f.f
- !
- MODULE CALCULATION
- CONTAINS
- SUBROUTINE CALC_DIST(x1,y1,x2,y2)
- IMPLICIT NONE
- REAL x1,y1,x2,y2
- REAL distance
- distance SQRT( (x2-x1)2 (y2-y1)2
) - WRITE(6,1) distance
- 1 FORMAT("The distance between the points
is ", 1pe13.5) - END SUBROUTINE CALC_DIST
- END MODULE CALCULATION
17Calling F90 module routines from C (C code)
- / FILENAME c_main_mod.c
- Shows how to call a FORTRAN routine from C
- In this case the FORTRAN routine, named
CALC_DIST, - is in the FORTRAN module named
calculation - /
- extern void __calculation_MOD_calc_dist(float ,
float , - float , float )
- void main()
-
- float p1_x,p1_y,p2_x,p2_y
- p1_x 0.0
- p1_y 0.0
- p2_x 3.0
- p2_y 4.0
- __calculation_MOD_calc_dist(p1_x,p1_y,p
2_x,p2_y)
18Calling F90 module routines from C (running)
- gt xlf90 -c calc_mod_f.f
- calculation End of Compilation 1
- 1501-510 Compilation successful for file
calc_mod_f.f. - gt cc -o c_calls_f_mod c_main_mod.c calc_mod_f.o
-lxlf90 -lm - gt ./c_calls_f_mod
- The distance between the points is 5.00000E00
19Handling character arguments
- FORTRAN passes (by value) an extra argument with
the length of the string - C assumes strings are a null-terminated sequence
of bytes - Can process this argument at the C end
- Can null-terminate strings at the FORTRAN end
- CALL TAKE_CHARS(b // CHAR(0))
- may also want REF
20Mixed case names
- -U option in xlf
- All functions, variables, and names become
case-sensitive - _at_PROCESS MIXED compiler directive
- on a specific compiler unit
21Design Issues
- Porting an existing code
- make and version control recommended
- Designing a new code
- FORTRAN for numbers
- C for strings
- (or avoid entirely)
- Maintaining portability
- Wrappers/shims useful
- make (but try to avoid code schism)
- Maybe -qextname
22Miscellaneous Issues
- Compiler options are frequent pitfall (or helper)
- including -qalign, -q32, -q64, -qautodbl,
-qintsize, -qnullterm, -qrealsize - Name conflicts can occur (e.g., main)
- -qextname can help (but with added complexity)
- Ditto -brename
- VAL and REF built-in functions
23Miscellaneous Issues (contd)
- -qextchk can help find errors ditto qsigtrap,
xl__trbk and -g - Funny FORTRAN function return values not
supported - pointer, array, or character of nonconstant
length - (not that I can make this work even with simple
examples) - Can share data structures C ? FORTRAN
- Cross-language I/O Just say no!
24Cross-language library calls
- No particular tricks as described above
- For C, function prototypes may be a challenge
- Can simply roll your own
- Load with xlf90 for FORTRAN libraries
- 64-bit or 32-bit uniformity ditto thread-safe
- Column-major (FORTRAN) vs. row-major (C) array
order
25Cross-language library call (example)
- !FILENAME wrap_s01baf.f
- !
- ! Gives an example of wrapping a
- ! Fortran function into a
- ! subroutine that can be called
- ! by even the most incompetent
- ! cross-language programmer, viz.
- ! - Mark Durst
- subroutine wrap_s01baf(x,y,i)
- double precision x, y
- integer i
- y s01baf(x,i)
- end subroutine wrap_s01baf
- / FILENAME c_nag.c
- Shows how to call a FORTRAN wrapper
- for a NAG routine from C
- /
- include ltstdio.hgt
- include ltmath.hgt
- extern void wrap_s01baf(double,double, int)
- main(int argc, char argv)
- double x, y
- int ifail
- x 1.0
- y 0.0
- wrap_s01baf(x,y, ifail)
- printf("f\n",y)
26Cross-language library call (running)
- gt xlf90 -c wrap_s01baf.f
- wrap_s01baf End of Compilation 1
- 1501-510 Compilation successful for file
wrap_s01baf.f. - gt cc -c c_nag.c
- gt module load nag
- gt xlf90 -o c_nag c_nag.o wrap_s01baf.o NAG
- gt ./c_nag
- 0.693147
27Further References
- Examples and most content are from
- http//www.nersc.gov/nusers/resources/software/ibm
/c_and_f.php - More details in XL Fortran Users Guide, Ch. 10
- http//www.nersc.gov/vendor_docs/ibm/xlf/html
- HPC Users ?Seaborg ? Software ? Compilers ? xlf
vendor ? Users Guide