在 Fortran 中获取 HDF5 文件名的长度?
Get length of HDF5 filename in Fortran?
我想在 Fortran 中获取 HDF5 对象的文件名,我事先不知道文件名的长度。 HDF5 文档说这可以通过将 NULL 传递给 h5fget_name:
来实现
If the length of the name, which determines the required value of size, is unknown, a preliminary H5Fget_name call can be made by setting name to NULL.
但是,尚不清楚如何从 Fortran 代码中完成此操作。根据文档中的上述语言,这样的事情应该有效:
function get_hdf5_filename(obj_id) result(filename)
use hdf5
use iso_c_binding, ONLY: c_null_ptr
! Arguments
integer(HID_T), intent(in)::obj_id
!! Handle of HDF5 object
! Result
character(:), allocatable::filename
integer(SIZE_T)::size = 0
!! Length of filename
integer::hdferr
!! HDF5 error code
call h5fget_name_f(obj_id, c_null_ptr, size, hdferr)
allocate (character(size)::filename)
call h5fget_name_f(obj_id, filename, size, hdferr)
end function get_hdf5_filename
但是,gfortran 不会编译上面的代码并给出类型不匹配错误:
Error: Type mismatch in argument 'buf' at (1); passed TYPE(c_ptr) to CHARACTER(1)
可以通过将文件名变量声明为指针并在初始调用 h5fget_name_f 之前将其无效来传递 null:
function get_hdf5_filename(obj_id) result(filename)
use hdf5
use iso_c_binding, ONLY: c_null_ptr
! Arguments
integer(HID_T), intent(in)::obj_id
!! Handle of HDF5 object
! Result
character(:), pointer::filename
integer(SIZE_T)::size = 50
!! Length of filename
integer::hdferr
!! HDF5 error code
nullify(filename)
call h5fget_name_f(obj_id, filename, size, hdferr)
! HDF5 needs one more character (probably for the null character terminating the string), so we allocate filename to length size+1
allocate (character(size+1)::filename)
call h5fget_name_f(obj_id, filename, size, hdferr)
! Remove last character from the returned string
filename => filename(1:size)
end function get_hdf5_filename
请注意,h5fget_name_f 在传递的字符串中需要一个额外的字符(可能是终止空字符),因此必须为名称指针分配一个比 size 参数中设置的值长的字符。可以通过使用数组切片语法(filename => filename(1:size)
在上例中)将文件指针重定向到排除最后一个字符的子集来删除终止空值。
一个可能的解决方案是创建一个 C 函数,returns 给定 HDF5 对象的文件名长度:
#include "hdf5.h"
#include "H5f90i.h"
int_f get_hdf5_filename_length(hid_t_f *obj_id){
return H5Fget_name((hid_t)*obj_id, NULL, 0);
}
可以通过以下方式从 Fortran 中调用:
function get_hdf5_filename(obj_id) result(filename)
use hdf5
use iso_c_binding, ONLY: c_null_ptr
interface
function get_hdf5_filename_length(obj_id) bind(c) result(length)
use hdf5
integer(HID_T)::obj_id
integer(SIZE_T)::length
end function get_hdf5_filename_length
end interface
! Arguments
integer(HID_T), intent(in)::obj_id
!! Handle of HDF5 object
! Result
character(:), pointer::filename
integer(SIZE_T)::size = 50
!! Length of filename
integer::hdferr
!! HDF5 error code
integer::i
!! Loop counter
size = get_hdf5_filename_length(obj_id)
! filename has to be allocated to size+1 to allow for the terminating null
! of the filename string in C
allocate (character(size+1)::filename)
! h5fget_name_f uses len_trim to determine the buffer length,
! which requires the buffer be filled with non-whitespace characters
! in order to work correctly
do i = 1, size + 1
filename(i:i) = 'a'
end do
! Get the filename
call h5fget_name_f(obj_id, filename, size, hdferr)
! Remove the null character from the end of the string
filename => filename(1:size)
end function get_hdf5_filename
请注意,将字符串缓冲区分配到正确的大小是不够的;在传递给 h5fget_name_f
之前,它还需要填充非空白字符,因为 h5fget_name_f
在传递的缓冲区上调用 len_trim
并使用结果来确定允许的最大文件名长度。
我想在 Fortran 中获取 HDF5 对象的文件名,我事先不知道文件名的长度。 HDF5 文档说这可以通过将 NULL 传递给 h5fget_name:
来实现If the length of the name, which determines the required value of size, is unknown, a preliminary H5Fget_name call can be made by setting name to NULL.
但是,尚不清楚如何从 Fortran 代码中完成此操作。根据文档中的上述语言,这样的事情应该有效:
function get_hdf5_filename(obj_id) result(filename)
use hdf5
use iso_c_binding, ONLY: c_null_ptr
! Arguments
integer(HID_T), intent(in)::obj_id
!! Handle of HDF5 object
! Result
character(:), allocatable::filename
integer(SIZE_T)::size = 0
!! Length of filename
integer::hdferr
!! HDF5 error code
call h5fget_name_f(obj_id, c_null_ptr, size, hdferr)
allocate (character(size)::filename)
call h5fget_name_f(obj_id, filename, size, hdferr)
end function get_hdf5_filename
但是,gfortran 不会编译上面的代码并给出类型不匹配错误:
Error: Type mismatch in argument 'buf' at (1); passed TYPE(c_ptr) to CHARACTER(1)
可以通过将文件名变量声明为指针并在初始调用 h5fget_name_f 之前将其无效来传递 null:
function get_hdf5_filename(obj_id) result(filename)
use hdf5
use iso_c_binding, ONLY: c_null_ptr
! Arguments
integer(HID_T), intent(in)::obj_id
!! Handle of HDF5 object
! Result
character(:), pointer::filename
integer(SIZE_T)::size = 50
!! Length of filename
integer::hdferr
!! HDF5 error code
nullify(filename)
call h5fget_name_f(obj_id, filename, size, hdferr)
! HDF5 needs one more character (probably for the null character terminating the string), so we allocate filename to length size+1
allocate (character(size+1)::filename)
call h5fget_name_f(obj_id, filename, size, hdferr)
! Remove last character from the returned string
filename => filename(1:size)
end function get_hdf5_filename
请注意,h5fget_name_f 在传递的字符串中需要一个额外的字符(可能是终止空字符),因此必须为名称指针分配一个比 size 参数中设置的值长的字符。可以通过使用数组切片语法(filename => filename(1:size)
在上例中)将文件指针重定向到排除最后一个字符的子集来删除终止空值。
一个可能的解决方案是创建一个 C 函数,returns 给定 HDF5 对象的文件名长度:
#include "hdf5.h"
#include "H5f90i.h"
int_f get_hdf5_filename_length(hid_t_f *obj_id){
return H5Fget_name((hid_t)*obj_id, NULL, 0);
}
可以通过以下方式从 Fortran 中调用:
function get_hdf5_filename(obj_id) result(filename)
use hdf5
use iso_c_binding, ONLY: c_null_ptr
interface
function get_hdf5_filename_length(obj_id) bind(c) result(length)
use hdf5
integer(HID_T)::obj_id
integer(SIZE_T)::length
end function get_hdf5_filename_length
end interface
! Arguments
integer(HID_T), intent(in)::obj_id
!! Handle of HDF5 object
! Result
character(:), pointer::filename
integer(SIZE_T)::size = 50
!! Length of filename
integer::hdferr
!! HDF5 error code
integer::i
!! Loop counter
size = get_hdf5_filename_length(obj_id)
! filename has to be allocated to size+1 to allow for the terminating null
! of the filename string in C
allocate (character(size+1)::filename)
! h5fget_name_f uses len_trim to determine the buffer length,
! which requires the buffer be filled with non-whitespace characters
! in order to work correctly
do i = 1, size + 1
filename(i:i) = 'a'
end do
! Get the filename
call h5fget_name_f(obj_id, filename, size, hdferr)
! Remove the null character from the end of the string
filename => filename(1:size)
end function get_hdf5_filename
请注意,将字符串缓冲区分配到正确的大小是不够的;在传递给 h5fget_name_f
之前,它还需要填充非空白字符,因为 h5fget_name_f
在传递的缓冲区上调用 len_trim
并使用结果来确定允许的最大文件名长度。