Linking C-routines to FORTRAN revisited

Hi!

Some time ago I had a C-routine that I wanted to link to my FORTRAN code. After some time I succeeded. Now I have a whole utility in C and want to convert it into a subroutine to be called from FORTRAN. My attempts until here were in vain, so I call for help at this place.

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. Here I already probably make some errors with pointers etc.

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.

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) mudule that links C-routines for the handling of bitmap-files, I find:

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 );

Adding the extra “*”-characters to the C-headers 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 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

You have obviously done a lot of work on this, and I commend you for it. However,
pgf90 data types that are NOT also fortran 77 data types, do not interface at all with
any language except pgf90. The 'INTENT(IN), for example, is such a case.

Best advice is to keep things simple. Since all fortran 77 arguments are by reference
only, it should be straightforward to write your C interface ‘wrapper’ to accept
nothing but the passed argument addresses (and string ‘lengths’). Within the C wrapper, you can then call the C routine as expected.

Such a wrapper works with pgf77, pgf90, pgCC, and other fortran compilers.
You also limit your language interface problems to a simple wrapper
library, the way libfmpich is a fortran wrapper for libmpich.