Performing File I/O from a FORTRAN Dynamic-Link Library

ID: Q102698


The information in this article applies to:
  • Microsoft FORTRAN for MS-DOS, version 5.1


SUMMARY

By calling the file I/O functions in the Windows application programming interface (API), a dynamic-link library (DLL) developed in Microsoft FORTRAN for the Microsoft Windows operating system can read from or write to binary or unformatted files. Invoking the Windows API to provide file I/O services for a FORTRAN DLL will also allow reliable access to the files from the program calling the DLL, even if the program was developed in Microsoft Visual Basic versions 2.0 and later.


MORE INFORMATION

The following FORTRAN code demonstrates file I/O on a binary or unformatted file using functions of the Windows API.

The code example below defines the data type used by the bfread and bfwrite functions as REAL*4. You can substitute another data type by changing the declaration in the interface statement.

If an application developed in Visual Basic calls a FORTRAN DLL that uses standard FORTRAN I/O statements to open and close a file, the file may not be available to the parent application. However, if the DLL opens or creates, accesses, and closes the file using functions in the Windows API, the file is available to the parent application or any other application as soon as the DLL closes the file.

The code example uses interface statements for the _hread and _hwrite functions instead of the _lread and _lwrite functions. (The latter functions can process only data items smaller than 64K but they may process these smaller items somewhat more efficiently.) The HUGE.LIB import library, created from HUGE.DEF, is required to call the huge versions of the read and write functions defined in version 3.1 of the Windows API. For more information on Windows API programming, please refer to the Windows SDK documentation.

Sample Code - FORTIO.FOR


C Open an existing file
      interface to integer*2 function lopen
     +  [pascal, alias:'_lopen'](filename, mode)
      character*1 filename[reference]
      integer*2   mode[value]
C        MODE =
C            0     Read-only
C            1     Write-only
C            2     Read and write
      end

C Create a file (erase the old file if one exists)
      interface to integer*2 function lcreat
     +  [pascal, alias:'_lcreat'](filename, mode)
      character*1 filename[reference]
      integer*2   mode[value]
C        MODE =
C            0     Read and write
C            1     Read-only
C            2     Hidden
C            3     System
      end

C Close a file (use with files opened by lcreat or lopen)
      interface to integer*2 function lclose
     +  [pascal, alias:'_lclose'](handle)
      integer*2   handle[value]
      end

C hread and hwrite can read or write a buffer larger than 64K
      interface to integer*4 function hwrite
     +  [pascal, alias:'_hwrite'](handle, buf, size)
      character*1 buf[reference]
      integer*2   handle[value]
      integer*4   size[value]
      end

      interface to integer*4 function hread
     +  [pascal, alias:'_hread'](handle, buf, size)
      character*1 buf[reference]
      integer*2   handle[value]
      integer*4   size[value]
      end

C Seek to a point in a file (used to provide direct file access)
      interface to integer*4 function llseek
     +  [pascal, alias:'_llseek'](handle, offset, origin)
      integer*4   offset[value]
      integer*2   handle[value], origin[value]
C        Origin =
C            0     Offset from start of file
C            1     Offset from current position
C            2     Offset from end of file
      end

C  Read and write binary floating-point data
      interface to integer*4 function bfwrite
     +  [pascal, alias:'_hwrite'](handle, buf, size)
      real*4      buf[reference](1)
      integer*2   handle[value]
      integer*4   size[value]
      end

      interface to integer*4 function bfread
     +  [pascal, alias:'_hread'](handle, buf, size)
      real*4      buf[reference](1)
      integer*2   handle[value]
      integer*4   size[value]
      end

C Write ASCII and binary data
      subroutine testwrite()
      character*30 str
      integer*2 handle, lclose, lcreat
      integer*4 i, hwrite, bfwrite
      real*4 x(20000)  ! Note: X is 80000 bytes

      handle = lcreat('testbf.out'C, 0) ! Create new file
      do i= 2, 20000
        x(i) = x(i - 1) + 3.1415926
      end do
      i = bfwrite(handle, x, 80000)    ! Binary write all of X
      i = lclose(handle)

      handle = lcreat('test.out'C, 0)   ! Create new file
      ! Use an internal write to format output text
      write(str, '(''Test One'', F12.5)') 51.763
      i = hwrite(handle, str, 20)       ! then write output text
      i = lclose(handle)
      end

C Read binary data
      subroutine readbinary()
      character*24 str
      integer*2 j, handle, lclose, lopen, lcreat
      integer*4 i, hwrite, bfread
      real*4 x(20000)  ! Note: X is 80000 bytes
      handle = lopen('testbf.out'C, 2) ! Open existing file
      i = bfread(handle, x, 80000)     ! Binary read all of X
      i = lclose(handle)

      handle = lcreat('testbf_o.out'C, 0) ! Create new file
      do j = 1, 4
         write(str, '(F16.5)') x(j)      ! Convert to text
         i = hwrite(handle, str, 16)     ! Write formatted output
      end do
      write(str, '(F16.5)') x(20000)
      i = hwrite(handle, str, 16)
      i = lclose(handle)
      end

C Randomly access a file
      subroutine testseek()
      character*40 str
      integer*2 handle, lclose, lopen
      integer*4 i, hwrite, llseek, hread

      handle = lopen('test.out'C, 2)
      i = llseek(handle, 4, 0)        ! Position to 4 bytes from start
      i = hread(handle, str, 16)      ! Read 16 characters
      i = llseek(handle, 7, 0)        ! Position to 7 bytes from start
      i = hwrite(handle, str, 16)     ! Overwrite from position 7 on
      i = lclose(handle)
      end

FORTIO.DEF
----------

LIBRARY        FORTIO
EXETYPE        WINDOWS 3.1
PROTMODE
CODE           PRELOAD MOVEABLE DISCARDABLE
DATA           PRELOAD MOVEABLE SINGLE
HEAPSIZE       1024
EXPORTS        WEP @1 RESIDENTNAME
               TESTWRITE
               TESTSEEK
               READBINARY

TEST.FOR
--------

       call testwrite
       print *,"testwrite - Created 'test.out' and 'testbf.out'"
       print *, 'Check them out (Hit return to continue)'
       read *
       call readbinary
       print *, "readbinary - Created 'testbf_o.out'"
       print *, 'Check it out (Hit return to continue)'
       read *
       call testseek   ! modify 'test.out'
       print *, "testseek - Modified 'test.out'"
       end

HUGE.DEF
--------

LIBRARY KERNEL
EXPORTS _hread
        _hwrite

FORTIO.MAK
----------

all: test.exe

test.exe: fortio.lib test.obj
   link /NOD test.obj, , nul, llibfew + fortio.lib,\ 
      c:\fortran\binb\fl.def;

test.obj: test.for
   fl /c /MW test.for

fortio.lib: fortio.dll
   implib fortio.lib fortio.dll

fortio.dll: fortio.obj fortio.def huge.lib
   link /NOD fortio.obj, fortio.dll, nul,\ 
       ldllfew.lib + huge.lib, fortio.def;

fortio.obj: fortio.for
   fl /c /Aw /Gw fortio.for

huge.lib: huge.def
   implib huge.lib huge.def 

Additional query words: kbinf 5.10

Keywords :
Version : :5.1
Platform :
Issue type :


Last Reviewed: October 29, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.