How to convert a C-utility into a subroutine and call it from gfortran?
Arjan van Dijk
Arjan.van.Dijk@rivm.nl
Tue Jun 19 09:21:00 GMT 2007
Hi!
I want to convert a C-utility into a subroutine and call it from FORTRAN.
My attempts until here were in vain, so I call for help at this place.
Some time ago I had a C-routine that I wanted to link to my FORTRAN
code. It wrote bitmapfiles. After some time I succeeded. Main
difference between my earlier problem and the present one is that now
I want to READ data FROM a file, whereas in the past I wanted to WRITE
data TO a file. Plus the conversion of a main program into a
subroutine.
Here is what I did:
I copied the utility xyz.c to xyzutils.c and changed:
int main(int argc, char **argv) {
into:
int read_xyz_record ( char *filein_name, long int
dump, int nx, int ny, float *array ) {
where filein_name and dump are supposed to be input variables, nx, ny
and array are supposed to be output variables. All names in the call
are original variable names in the main part of the utility. Here I
already probably make some errors with pointers etc. Something with
pass-by-reference and pass-by-value.
My experience with this or with C is very limited.
I wrote a wrap-function read_xyz_record_, which has an extra
underscore and which simply calls read_xyz_record, just to make sure
that FORTRAN will find the C-routine (with -fno-underscoring this is
not necessary).
I made a headerfile xyzutils.h, which contains just the headers of
functions read_xyz_record and read_xyz_record_:
int read_xyz_record ( char *filein_name, long int dump, int nx, int
ny, float *array );
int read_xyz_record_ ( char *filein_name, long int dump, int nx, int
ny, float *array );
Then, I wrote a fortran module libxyz.f90, containing the following
interface:
interface integer function
read_xyz_record(file,dump,nx,ny,darr) character(*), intent(in) ::
file integer, intent(in) :: dump, nx, ny REAL(4),
dimension(*), intent(out) :: darr end function
read_xyz_record end interface
and a subroutine that calls read_xys_record as follows:
SUBROUTINE Readxyzje(fname,recnr,darray) CHARACTER(*), INTENT(IN) ::
fname INTEGER, INTENT(IN) :: recnr REAL(4), INTENT(INOUT),
DIMENSION(:) :: darray INTEGER :: Rv,NX,NY Rv =
read_xyz_record(fname//char(0),%val(RecNr),%val(nx),
%val(ny),darray)
! END SUBROUTINE Readxyzje
When I compile a simple test program that just calls fortran routine
readxyzje on a file and then makes an ASCII-dump of the resulting
array, I get a bunch of zeros.
In my (working) module that links C-routines for the handling of
bitmap-files, I find the following difference between the use of input
arrays and output arrays in subroutine calls (taken from the
headerfile):
int bmp_read ( char *filein_name, int *xsize, int *ysize, int
**rarray, int **garray, int **barray );
int bmp_write ( char *fileout_name, int xsize, int ysize, int *rarray,
int *garray, int *barray );
In my bitmap module, I only used bmp_write, so I wouldn't know how to
properly call bmp_read. Adding some extra "*"-characters to the C-
headers of the present subroutines didn't bring what I hoped for...
Probably not only the C-routine needs some modification, but also the
call to it in the fortran routine and maybe the interface declaration
in the module file need some attention. Who can tell me how I can make
a working fortran routine from the available C-utility?
Best regards and thanks ahead for all contributions,
Arjan
Arjan.van.Dijk@RIVM.nl
____________________________________________________________________________
DISCLAIMER: http://www.rivm.nl/disclaimer.htm
More information about the Fortran
mailing list