1 / 27

270 likes | 817 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.

Download Presentation
## Mixed Language Programming on Seaborg

**An Image/Link below is provided (as is) to download presentation**
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.
Content is provided to you AS IS for your information and personal use only.
Download presentation by click this link.
While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
During download, if you can't get a presentation, the file might be deleted by the publisher.

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

More Related