Interfacing between Fortran and C - a little utility
- From: Arjen Markus <arjen.markus@xxxxxxxxxx>
- Date: Thu, 29 May 2008 00:04:35 -0700 (PDT)
Hello,
for many years I have been using all manner of methods to interface
between Fortran
and C and I welcome the facilities that Fortran 2003 offers. But until
the time that
Fortran compilers can be counted on to adhere to that standard (and in
particular
the C bindings part), here is a little program that I recently
concocted to solve
several problems:
- It automatically determines what naming convention is used (from the
set of
conventions that I have come across over the years)
- It automatically determines if the hidden string length argument
appears after
the string argument or not
- It tries to determine if - on Windows - the __stdcall calling
convention is used or not.
This part is a bit shaky - it relies on the use of the MS Visual C/C+
+ compiler for
the C code. I have not checked if this convention is also used with
gcc on Cygwin or
MinGW. Still, the program can be easily adjusted if that is the
case.
It consists of a Fortran main program and a set of C routines - the
trick is that
each of these routines does the same thing but only one is called,
picked up by the
linker as a consequence of the Fortran naming convention :). I
developed it in the
context of my Ftcl project (http://ftcl.sourceforge.net), hence the
references to Tcl.
Maybe this will be helpful for others as well.
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 _MSV_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 ) ;
}
.
- Follow-Ups:
- Prev by Date: Re: problem with very small numbers - g95 versus gfortran
- Next by Date: Re: problem with very small numbers - g95 versus gfortran
- Previous by thread: 1.0d0 stored as integer?
- Next by thread: Re: Interfacing between Fortran and C - a little utility
- Index(es):
Relevant Pages
|
|