270 likes | 290 Views
Mixed Language Programming on Seaborg. Mark Durst NERSC User Services. Overview. 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.
E N D
Mixed Language Programming on Seaborg Mark Durst NERSC User Services 1
Overview • 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 2
Calling 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 4
!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 <math.h> 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); } Calling C from FORTRAN (example) 5
Calling C from FORTRAN (running) > cc -c calc_c.c > 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. > ./f_calls_c The distance between the points is 5.00000e+00 6
Calling FORTRAN from C • Again, calling by reference most straightforward • Must specify –lxlf90 –lm in cc command • Or use xlf90 to load 7
/* 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 Calling FORTRAN from C (example) 8
Calling FORTRAN from C (running) > xlf90 -c calc_f.f ** calc_dist === End of Compilation 1 === 1501-510 Compilation successful for file calc_f.f. > cc -o c_calls_f c_main.c calc_f.o -lxlf90 -lm > ./c_calls_f The distance between the points is 5.00000E+00 9
Calling 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 • xlCcommand must be used to link 10
/* FILENAME: calc_c++.h This is the C++ routine. */ #include <iostream.h> #include <math.h> template<class T> class calc { public: calc() {cout <<"Inside C++ constructor"<<endl;} ~calc() {cout <<"Inside C++ destructor"<<endl;} 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 <<"The distance between the points is " <<distance<<" \n"<<endl; } }; Calling C++ from FORTRAN (C++ code) 11
Calling C++ from FORTRAN (C wrapper) /* Filename: calc_cwrapper.C */ #include <stdio.h> #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"); calc<float>* c=new calc<float>(); c->calc_dist(x,y,X,Y); printf("Back in C function, will delete C++ object\n"); delete c; } 12
Calling C++ from FORTRAN (running) > xlf90 -c f_main.f ** f_calls_c === End of Compilation 1 === 1501-510 Compilation successful for file f_main.f. > xlC -c calc_cwrapper.C > xlC -o f_calls_c++ calc_cwrapper.o f_main.o -lm -lxlf90 > ./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 13
Calling FORTRAN from C++ • Can simply declare FORTRAN subroutine like C: extern "C" void fortran_routine_name • Or with FORTRAN function: extern "C" return_typefortran_routine_name 14
Calling F90 module routines from C • Refer to FORTRAN routine as __modulename_MOD_routinename • There is apparently a way for C to read prototype info out of .mod files 15
Calling 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 16
Calling 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,&p2_x,&p2_y); } 17
Calling F90 module routines from C (running) > xlf90 -c calc_mod_f.f ** calculation === End of Compilation 1 === 1501-510 Compilation successful for file calc_mod_f.f. > cc -o c_calls_f_mod c_main_mod.c calc_mod_f.o -lxlf90 -lm > ./c_calls_f_mod The distance between the points is 5.00000E+00 18
Handling 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 19
Mixed case names • -U option in xlf • All functions, variables, and names become case-sensitive • @PROCESS MIXED compiler directive • on a specific compiler unit 20
Design 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 21
Miscellaneous 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 22
Miscellaneous Issues (cont’d) • -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 CFORTRAN • Cross-language I/O: Just say no! 23
Cross-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 24
!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 <stdio.h> #include <math.h> 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); } Cross-language library call(example) 25
Cross-language library call (running) > xlf90 -c wrap_s01baf.f ** wrap_s01baf === End of Compilation 1 === 1501-510 Compilation successful for file wrap_s01baf.f. > cc -c c_nag.c > module load nag > xlf90 -o c_nag c_nag.o wrap_s01baf.o $NAG > ./c_nag 0.693147 26
Further References • Examples and most content are from http://www.nersc.gov/nusers/resources/software/ibm/c_and_f.php • More details in XL Fortran User’s Guide, Ch. 10 http://www.nersc.gov/vendor_docs/ibm/xlf/html • HPC Users Seaborg Software Compilers xlf vendor User’s Guide 27