【问题标题】:Why does print statement change gzread behavior?为什么 print 语句会改变 gzread 行为?
【发布时间】:2014-01-09 21:10:33
【问题描述】:

我正在尝试使用 zlib library 中的 C 函数 gzopen、gzread 和 gzclose 在 Fortran 中读取 gzip 文件。我的子例程在包含打印语句时可以正常工作,但在没有它的情况下会给出Z_STREAM_ERROR (-2)。是什么导致这种情况发生,我该如何解决?

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

我在 CentOS 上编译:

gfortran -o example_usage.exe example_usage.f90 /lib64/libz.so.1

数据文件位于this site

【问题讨论】:

  • 返回-2究竟是什么? gzread() 只能返回读取的非负字节数,或 -1 表示错误。
  • francescalus:是的,确实!马克:我从“isize = gzread(gzfile,abuf,size(abuf))”得到 isize=-2

标签: c fortran gzip gfortran fortran-iso-c-binding


【解决方案1】:

在子程序fastunzip 中声明logical :: c_associated。但是,您通过使用关联(iso_c_binding)获得此功能,因此您应该删除该行。

我安装的 gfortran (4.8) 将其标记为错误,所以我猜你有一个旧版本?但是,一旦我删除该行,即使没有 print,您的代码似乎也可以工作,所以也许这值得您尝试。

在风格说明上,我推荐use, intrinsic :: iso_c_binding,甚至可能使用only(这也会向您表明c_associated 是通过使用关联)。

【讨论】:

  • francescalus:“逻辑”声明正是问题所在,感谢您的“唯一”建议……哎呀,我使用的是 gfortran 4.4
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 2011-09-04
  • 1970-01-01
  • 2021-03-06
相关资源
最近更新 更多