I'm trying to get the filename of an HDF5 object in Fortran, for which I do not know the length of the filename in advance. The HDF5 documentation says this can be accomplished by passing NULL to 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.
However, it is unclear how to accomplish this from Fortran code. Per the above language in the documentation, something like this should work:
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
However, gfortran won't compile the above and gives a type mismatch error:
Error: Type mismatch in argument 'buf' at (1); passed TYPE(c_ptr) to CHARACTER(1)
A possible solution is to create a C function that returns the filename length for a given HDF5 object:
#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);
}
which can be called from Fortran in the following way:
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
Note that it is not enough to allocate the string buffer to the correct size; it also needs to be populated with non-whitespace characters before being passed to h5fget_name_f
, because h5fget_name_f
calls len_trim
on the passed buffer and uses the result to determine the maximum permissible filename length.