¿Por qué print statement cambia el comportamiento de gzread?
fortran gzip (1)
Intento leer un archivo gzip en Fortran usando las funciones C gzopen, gzread y gzclose de la biblioteca zlib . Mi subrutina funciona correctamente cuando contiene una instrucción de impresión, pero da un Z_STREAM_ERROR (-2)
sin ella. ¿Qué está causando esto y cómo puedo solucionarlo?
module gzmodule
use :: iso_c_binding
implicit none
private
public fastunzip
interface
type(c_ptr) function gzopen(filename,mode) bind(c)
use :: iso_c_binding
character(kind=c_char), dimension(*) :: filename
character(kind=c_char), dimension(*) :: mode
end function gzopen
end interface
interface
integer(c_int) function gzread(gzfile,buffer,length) bind(c)
use :: iso_c_binding
type(c_ptr), value :: gzfile
character(len=1,kind=c_char) :: buffer(*)
integer(c_int) :: length
end function gzread
end interface
interface
integer(c_int) function gzclose(gzfile) bind(c)
use :: iso_c_binding
type(c_ptr), value :: gzfile
end function
end interface
contains
subroutine fastunzip(filename, isize,abuf,ierr)
use :: iso_c_binding
character(len=*,kind=c_char), intent(in) :: filename
integer(c_int), intent(out) :: isize
character(len=1,kind=c_char), intent(inout) :: abuf(:,:,:,:)
integer(4), intent(out) :: ierr
type(c_ptr) :: gzfile
integer(c_int) :: iclose
logical :: c_associated
ierr = 1 !! indicates that an error has occured
isize = 0
gzfile = gzopen(trim(filename)//c_null_char,"rb")
if (.not.c_associated(gzfile)) return
isize = gzread(gzfile,abuf,size(abuf))
print*,isize !! why do I need this for it to work?
if (isize.ne.size(abuf)) return
iclose = gzclose(gzfile)
if (iclose.ne.0) return
ierr = 0 !! success
end subroutine fastunzip
end module gzmodule
program main
use gzmodule
implicit none
character(100) :: filename = ''./f10_19950120v7.gz''
integer(4) :: isize
integer(4) :: ierr
logical(4) :: exists
integer(4), parameter :: nlon = 1440
integer(4), parameter :: nlat = 720
integer(4), parameter :: nvar = 5
integer(4), parameter :: nasc = 2
character(1) :: abuf(nlon,nlat,nvar,nasc)
inquire(file=filename,exist=exists)
if (.not.exists) stop ''file not found''
call fastunzip(filename, isize,abuf,ierr)
print*,''return value of isize '',isize
if (ierr.ne.0) stop ''error in fastunzip''
print*,''done''
end program main
Estoy en CentOS y compilando con:
gfortran -o example_usage.exe example_usage.f90 /lib64/libz.so.1
y el archivo de datos está disponible en este sitio .
En la subrutina fastunzip
declaras logical :: c_associated
. Sin embargo, obtienes esta función mediante la asociación de uso (de iso_c_binding
), por lo que debes eliminar esa línea.
Mi gfortran instalado (4.8) lo marca como un error, ¿así que supongo que tienes una versión anterior? Pero una vez que elimino esa línea, su código parece funcionar incluso sin la print
, por lo que quizás valga la pena intentarlo.
En una nota de estilo, recomendaría use, intrinsic :: iso_c_binding
, quizás incluso con only
(lo que también c_associated
que c_associated
es a través de la asociación de uso).