I'm looking to work with older Fortran subroutines that read from file-based unit numbers. Here is an example of some fixed-format FORTRAN77, reader.f:
SUBROUTINE READER(IN,FVAL)
IMPLICIT NONE
INTEGER IN
REAL FVAL
PRINT *,'READER READING FROM',IN
READ(IN,*) FVAL
PRINT *,'READER DONE',FVAL
RETURN
END
Compile this to a shared library, on Linux:
gfortran -fPIC -shared -o libdusty.so reader.f
And here is a basic ctypes interface to the library object in Python:
import os
from ctypes import CDLL, POINTER, c_int32, c_float, byref
c_int32_p = POINTER(c_int32)
c_float_p = POINTER(c_float)
so = CDLL('./libdusty.so')
reader = so.reader_
reader.argtypes = [c_int32_p, c_float_p]
reader.restype = None
Without an open statement, Fortran reads from the file #.fort, where # is the file unit number. So continuing from above, I get Python to write a temporary file to read from:
fval_in = 43.21
fnum_in = 12
fname_in = 'fort.' + str(fnum_in)
print('Writing ' + fname_in)
with open(fname_in, 'w') as fp:
fp.write(str(fval_in) + '\n')
fval_out = c_float(0)
reader(byref(c_int32(fnum_in)), byref(fval_out))
print('Received fval: ' + str(fval_out.value))
os.unlink(fname_in)
From a console (which receives stdout), here the full output:
Writing fort.12
READER READING FROM 12
READER DONE 43.2099991
Received fval: 43.2099990845
Question: is a disk-based file object necessary, or is it possible to use a non-file-based stream to read from? A good candidate is io.BytesIO, except that it does not provide fileno(). And a related question: is it possible to use a different file name other than fort.12 in this example?
fort.12. Now, it does turn out that many popular Fortran processor use a de facto standard naming convention that matchesfort.12. The Fortran standard does not requirefort.12to be disk-based. Of course, you can use a different filename, but that would require you to use theOPENstatement to connect the unit number 12 to the specific file. - Stevefort.12name is not really part of any standard, which is why I'd like to no do that. I can probably add another subroutine to the library toOPENsomething that returns a valid unit number that the other subroutine can utilize. However, I'm still not sure ifOPENsupports any kind of non-disk-based filestream (like a memory-map). - Mike T