> On 2008-06-25 16:32+0200 Bernd Schubert wrote: > >> No, it is really no problem to link fortran libraries and to call their >> functions. It is onkly a bit nasty sometimes to write the proto types of >> the >> blas/lapack functions, since nobody seems to have created a complete set >> of >> these, afaik. For real number crunching one also uses the intel/amd or >> goto >> libraries and there is always only one library of these, for both C and >> Fortran (afaik, these optimized libraries are also not written in >> fortran >> anymore, they just have this stupid interface to be compatible with >> fortran. >> The other issue with fortran libraries is to figure out, how these have >> been >> compiled (additional underscores, etc). > > You have described issues which illustrate and support my point. They may > be > considered fairly trivial on one fixed platform but become important if > you > are trying to make a multi-platform build system. For example, what do > you > do about the underscore issue if you are testing the linking of C code > with > the fortran blas library? On one platform you will have to test sgemm, on > another you will have to test sgemm_. These cross-platform build-system > issues all disappear if you test C/C++ code against the C version of blas. > >> >> On the other hand, cblas even has a slightly different interface than >> nativ >> blas, so without changing the existing code it is not suitable for >> linking. >> > > Changing your existing code once to link to cblas may be a smaller price > to > pay. If your existing C/C++ code linked to the fortran BLAS library is to > work on multiple platforms, what do you do about the cross-platform issue > involving underscores? You will end up doing a lot of extra work to > support > the platform variations that is not required if you link to the C version > of > BLAS. >
With regards to the differences in calling and naming conventions between Fortran and C, I recently posted a program on the comp.lang.fortran newsgroup to solve that issue automatically, at least for the platforms I have access to. It is part of my Ftcl project, the combination of Fortran and Tcl - http://ftcl.sf.net. I post it below, as it may help solving the current issue. The idea is very simple: Let the linker decide which version of a C routine will be called by the Fortran program and let that version write its properties to a header file. Regards, Arjen ----- probe.f90 ----- ! probe.f90 -- ! Try and identify the Fortran naming and calling convention ! - part of Ftcl ! ! Note: ! This is the Fortran part of a program that uses a few tricks ! to determine: ! - The naming convention for the Fortran compiler (including ! the current options that influence this convention). ! The result will be: ! - One of FOR_ALL_LOWER, FOR_ALL_CAPS, FOR_UNDERSCORE or FOR_DBL_UNDERSCORE ! will be defined. These are the most common naming conventions ! - The macro IN_BETWEEN is defined or undefined so that string ! arguments can be properly passed ! - The macro FOR_CALL is defined to capture the correct calling ! convention vis-a-vis stack clean-up ! - The values of these macros are stored in a file "ftcl_conventions.h" ! ! If the program fails, it will need to be expanded, as that is an ! indication that this particular combination of Fortran and C ! compilers is not yet supported. ! program probe character(len=7) :: first = 'Fortran' character(len=3) :: second = 'Tcl' call probe_c( first, second ) end program probe ----- probe_c.c ----- /* probe_c.c -- * Companion to the file probe.f90. Together they form a program * that will write a header file with the right macros for * setting up the interface between Fortran and C. * */ #include <stdio.h> #include <stdlib.h> /* probe_c -- Plainly named version */ void probe_c( char *first, int len_first, char *second, int len_second ) { FILE *outfile ; outfile = fopen( "ftcl_conventions.h", "w" ) ; fprintf( outfile, "#define FOR_ALL_LOWER\n" ) ; fprintf( outfile, "#define FOR_CALL\n" ) ; /* If hidden length argument in between, then len_first must be 7 */ if ( len_first == 7 ) { fprintf( outfile, "#define IN_BETWEEN\n" ) ; } else if ( (int) second == 7 ) { fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } else { fprintf( stderr, "Unknown expected calling convention - assuming NOT IN_BETWEEN!\n" ) ; fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } fclose( outfile ) ; } /* PROBE_C -- All capitals version - possibly __stdcall too */ #ifdef _MSC_VER #define FOR_CALL __stdcall #else #define FOR_CALL #endif void FOR_CALL PROBE_C( char *first, int len_first, char *second, int len_second ) { FILE *outfile ; outfile = fopen( "ftcl_conventions.h", "w" ) ; fprintf( outfile, "#define FOR_ALL_CAPS\n" ) ; #ifdef _MSC_VER fprintf( outfile, "#define FOR_CALL __stdcall\n" ) ; #else fprintf( outfile, "#define FOR_CALL\n" ) ; #endif /* If hidden length argument in between, then len_first must be 7 */ if ( len_first == 7 ) { fprintf( outfile, "#define IN_BETWEEN\n" ) ; } else if ( (int) second == 7 ) { fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } else { fprintf( stderr, "Unknown expected calling convention - assuming NOT IN_BETWEEN!\n" ) ; fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } fclose( outfile ) ; } /* probe_c_ -- Single underscore */ void FOR_CALL probe_c_( char *first, int len_first, char *second, int len_second ) { FILE *outfile ; outfile = fopen( "ftcl_conventions.h", "w" ) ; fprintf( outfile, "#define FOR_UNDERSCORE\n" ) ; fprintf( outfile, "#define FOR_CALL\n" ) ; /* If hidden length argument in between, then len_first must be 7 */ if ( len_first == 7 ) { fprintf( outfile, "#define IN_BETWEEN\n" ) ; } else if ( (int) second == 7 ) { fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } else { fprintf( stderr, "Unknown expected calling convention - assuming NOT IN_BETWEEN!\n" ) ; fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } fclose( outfile ) ; } /* probe_c__ -- Double underscore (for Fortran names that have an embedded underscore) */ void FOR_CALL probe_c__( char *first, int len_first, char *second, int len_second ) { FILE *outfile ; outfile = fopen( "ftcl_conventions.h", "w" ) ; fprintf( outfile, "#define FOR_DBL_UNDERSCORE\n" ) ; fprintf( outfile, "#define FOR_CALL\n" ) ; /* If hidden length argument in between, then len_first must be 7 */ if ( len_first == 7 ) { fprintf( outfile, "#define IN_BETWEEN\n" ) ; } else if ( (int) second == 7 ) { fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } else { fprintf( stderr, "Unknown expected calling convention - assuming NOT IN_BETWEEN!\n" ) ; fprintf( outfile, "#undef IN_BETWEEN\n" ) ; } fclose( outfile ) ; } _______________________________________________ CMake mailing list CMake@cmake.org http://www.cmake.org/mailman/listinfo/cmake