Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap more of the HDF5 API with generated bindings #677

Merged
merged 1 commit into from
Sep 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions gen/api_defs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@

@bind h5_close()::Herr "Error closing the HDF5 resources"
@bind h5_dont_atexit()::Herr "Error calling dont_atexit"
@bind h5_free_memory(buf::Ptr{Cvoid})::Herr "Error freeing memory"
@bind h5_garbage_collect()::Herr "Error on garbage collect"
@bind h5_get_libversion(majnum::Ref{Cuint}, minnum::Ref{Cuint}, relnum::Ref{Cuint})::Herr "Error getting HDF5 library version"
@bind h5_open()::Herr "Error initializing the HDF5 library"
@bind h5_set_free_list_limits(reg_global_lim::Cint, reg_list_lim::Cint, arr_global_lim::Cint, arr_list_lim::Cint, blk_global_lim::Cint, blk_list_lim::Cint)::Herr "Error setting limits on free lists"

Expand Down Expand Up @@ -69,6 +71,7 @@
### Error Interface
###

@bind h5e_get_auto(estack_id::Hid, func::Ref{Ptr{Cvoid}}, client_data::Ref{Ptr{Cvoid}})::Herr "Error getting error reporting behavior"
@bind h5e_set_auto(estack_id::Hid, func::Ptr{Cvoid}, client_data::Ptr{Cvoid})::Herr "Error setting error reporting behavior"

###
Expand All @@ -82,6 +85,8 @@
@bind h5f_get_create_plist(file_id::Hid)::Hid "Error getting file create property list"
@bind h5f_get_intent(file_id::Hid, intent::Ptr{Cuint})::Herr "Error getting file intent"
@bind h5f_get_name(obj_id::Hid, buf::Ptr{UInt8}, buf_size::Csize_t)::Cssize_t "Error getting file name"
@bind h5f_get_obj_count(file_id::Hid, types::Cuint)::Cssize_t "Error getting object count"
@bind h5f_get_obj_ids(file_id::Hid, types::Cuint, max_objs::Csize_t, obj_id_list::Ptr{Hid})::Cssize_t "Error getting objects"
@bind h5f_get_vfd_handle(file_id::Hid, fapl_id::Hid, file_handle::Ptr{Ptr{Cint}})::Herr "Error getting VFD handle"
@bind h5f_is_hdf5(pathname::Cstring)::Htri error("Cannot access file ", pathname)
@bind h5f_open(pathname::Cstring, flags::Cuint, fapl_id::Hid)::Hid error("Error opening file ", pathname)
Expand Down Expand Up @@ -178,6 +183,7 @@
###

@bind h5r_create(ref::Ptr{HDF5ReferenceObj}, loc_id::Hid, pathname::Ptr{UInt8}, ref_type::Cint, space_id::Hid)::Herr error("Error creating reference to object ", hi5_get_name(loc_id), "/", pathname)
@bind h5r_dereference(obj_id::Hid, ref_type::Cint, ref::Ref{HDF5ReferenceObj})::Hid "Error dereferencing object"
@bind h5r_get_obj_type(loc_id::Hid, ref_type::Cint, ref::Ptr{Cvoid}, obj_type::Ptr{Cint})::Herr "Error getting object type"
@bind h5r_get_region(loc_id::Hid, ref_type::Cint, ref::Ptr{Cvoid})::Hid "Error getting region from reference"

Expand Down Expand Up @@ -228,6 +234,10 @@
@bind h5t_set_size(dtype_id::Hid, sz::Csize_t)::Herr "Error setting size of datatype"
@bind h5t_set_strpad(dtype_id::Hid, sz::Cint)::Herr "Error setting size of datatype"
@bind h5t_vlen_create(base_type_id::Hid)::Hid "Error creating vlen type"
# The following are not autoatically wrapped since they have requirements about freeing
# the memory that is returned from the calls.
#@bind h5t_get_member_name(dtype_id::Hid, index::Cuint)::Cstring error("Error getting name of compound datatype member #", index)
#@bind h5t_get_tag(type_id::Hid)::Cstring "Error getting datatype opaque tag"

###
### Optimized Functions Interface
Expand All @@ -236,6 +246,12 @@
@bind h5do_append(dset_id::Hid, dxpl_id::Hid, index::Cuint, num_elem::Hsize, memtype::Hid, buffer::Ptr{Cvoid})::Herr "error appending"
@bind h5do_write_chunk(dset_id::Hid, dxpl_id::Hid, filter_mask::Int32, offset::Ptr{Hsize}, bufsize::Csize_t, buf::Ptr{Cvoid})::Herr "Error writing chunk"

###
### HDF5 Lite Interface
###

@bind h5lt_dtype_to_text(datatype::Hid, str::Ptr{UInt8}, lang_type::Cint, len::Ref{Csize_t})::Herr "Error getting datatype text representation"

###
### Table Interface
###
Expand Down
4 changes: 3 additions & 1 deletion gen/bind_generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ const bind_exceptions = Dict{Symbol,Symbol}()
push!(bind_exceptions, :h5a_create => :H5Acreate2)
push!(bind_exceptions, :h5d_create => :H5Dcreate2)
push!(bind_exceptions, :h5d_open => :H5Dopen2)
push!(bind_exceptions, :h5e_get_auto => :H5Eget_auto2)
push!(bind_exceptions, :h5e_set_auto => :H5Eset_auto2)
push!(bind_exceptions, :h5g_create => :H5Gcreate2)
push!(bind_exceptions, :h5g_open => :H5Gopen2)
push!(bind_exceptions, :h5o_get_info => :H5Oget_info1)
push!(bind_exceptions, :h5p_get_filter_by_id => :H5Pget_filter_by_id2)
push!(bind_exceptions, :h5r_dereference => :H5Rdereference1)
push!(bind_exceptions, :h5r_get_obj_type => :H5Rget_obj_type2)
push!(bind_exceptions, :h5t_array_create => :H5Tarray_create2)
push!(bind_exceptions, :h5t_commit => :H5Tcommit2)
Expand Down Expand Up @@ -105,7 +107,7 @@ macro bind(sig::Expr, err::Union{String,Expr,Nothing} = nothing)
end

# Determine the underlying C library to call
lib = startswith(string(cfuncname), r"H5(DO|TB)") ? :libhdf5_hl : :libhdf5
lib = startswith(string(cfuncname), r"H5(DO|LT|TB)") ? :libhdf5_hl : :libhdf5

# Now start building up the full expression:
statsym = Symbol("#status#") # not using gensym() to have stable naming
Expand Down
58 changes: 19 additions & 39 deletions src/HDF5.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ include("datafile.jl")

function h5_get_libversion()
jmert marked this conversation as resolved.
Show resolved Hide resolved
majnum, minnum, relnum = Ref{Cuint}(), Ref{Cuint}(), Ref{Cuint}()
# Note: direct ccall because api.jl hasn't been sourced yet.
status = ccall((:H5get_libversion, libhdf5), Cint, (Ptr{Cuint}, Ptr{Cuint}, Ptr{Cuint}), majnum, minnum, relnum)
status < 0 && error("Error getting HDF5 library version")
VersionNumber(majnum[], minnum[], relnum[])
Expand Down Expand Up @@ -1965,14 +1966,6 @@ h5l_exists(loc_id::Hid, name::String) = h5l_exists(loc_id, name, H5P_DEFAULT)
h5o_open(obj_id::Hid, name::String) = h5o_open(obj_id, name, H5P_DEFAULT)
#h5s_get_simple_extent_ndims(space_id::Hid) = h5s_get_simple_extent_ndims(space_id, C_NULL, C_NULL)
h5t_get_native_type(type_id::Hid) = h5t_get_native_type(type_id, H5T_DIR_ASCEND)
function h5r_dereference(obj_id::Hid, ref_type::Integer, pointee::HDF5ReferenceObj)
ret = ccall((:H5Rdereference1, libhdf5), Hid, (Hid, Cint, Ref{HDF5ReferenceObj}),
obj_id, ref_type, pointee)
if ret < 0
error("Error dereferencing object")
end
ret
end

# Core API ccall wrappers
include("api.jl")
Expand Down Expand Up @@ -2005,15 +1998,10 @@ end

function h5lt_dtype_to_text(dtype_id)
len = Ref{Csize_t}()
status = ccall((:H5LTdtype_to_text, libhdf5_hl), Herr, (Hid, Ptr{UInt8}, Int, Ref{Csize_t}), dtype_id, C_NULL, 0, len)
status < 0 && error("Error getting dtype text representation")

buf = Base.StringVector(len[]-1)
status = ccall((:H5LTdtype_to_text, libhdf5_hl), Herr, (Hid, Ptr{UInt8}, Int, Ref{Csize_t}), dtype_id, buf, 0, len)
status < 0 && error("Error getting dtype text representation")

dtype_text = String(buf)
return dtype_text
h5lt_dtype_to_text(dtype_id, C_NULL, 0, len)
buf = Base.StringVector(len[] - 1)
h5lt_dtype_to_text(dtype_id, buf, 0, len)
return String(buf)
end

function h5s_get_simple_extent_dims(space_id::Hid)
Expand All @@ -2023,36 +2011,31 @@ function h5s_get_simple_extent_dims(space_id::Hid)
h5s_get_simple_extent_dims(space_id, dims, maxdims)
return tuple(reverse!(dims)...), tuple(reverse!(maxdims)...)
end
# Note: The following two functions implement direct ccalls because the binding generator
# cannot (yet) do the string wrapping and memory freeing.
function h5t_get_member_name(type_id::Hid, index::Integer)
pn = ccall((:H5Tget_member_name, libhdf5), Ptr{UInt8}, (Hid, Cuint), type_id, index)
if pn == C_NULL
error("Error getting name of compound datatype member #", index)
end
s = unsafe_string(pn)
Libc.free(pn)
s
h5_free_memory(pn)
return s
end
function h5t_get_tag(type_id::Hid)
pc = ccall((:H5Tget_tag, libhdf5),
Ptr{UInt8},
(Hid,),
type_id)
pc = ccall((:H5Tget_tag, libhdf5), Ptr{UInt8}, (Hid,), type_id)
if pc == C_NULL
error("Error getting opaque tag")
end
s = unsafe_string(pc)
Libc.free(pc)
s
h5_free_memory(pc)
return s
end

function h5f_get_obj_ids(file_id::Hid, types::Integer)
sz = ccall((:H5Fget_obj_count, libhdf5), Int, (Hid, UInt32),
file_id, types)
sz >= 0 || error("error getting object count")
hids = Vector{Hid}(undef,sz)
sz2 = ccall((:H5Fget_obj_ids, libhdf5), Int, (Hid, UInt32, UInt, Ptr{Hid}),
file_id, types, sz, hids)
sz2 >= 0 || error("error getting objects")
sz = h5f_get_obj_count(file_id, types)
hids = Vector{Hid}(undef, sz)
sz2 = h5f_get_obj_ids(file_id, types, sz, hids)
sz2 != sz && resize!(hids, sz2)
hids
end
Expand Down Expand Up @@ -2182,14 +2165,11 @@ function hiding_errors(f)
# error_stack = ccall((:H5Eget_current_stack, libhdf5), Hid, ())
old_func = Ref{Ptr{Cvoid}}()
old_client_data = Ref{Ptr{Cvoid}}()
ccall((:H5Eget_auto2, libhdf5), Herr, (Hid, Ptr{Ptr{Cvoid}}, Ptr{Ptr{Cvoid}}),
error_stack, old_func, old_client_data)
ccall((:H5Eset_auto2, libhdf5), Herr, (Hid, Ptr{Cvoid}, Ptr{Cvoid}),
error_stack, C_NULL, C_NULL)
h5e_get_auto(error_stack, old_func, old_client_data)
h5e_set_auto(error_stack, C_NULL, C_NULL)
res = f()
ccall((:H5Eset_auto2, libhdf5), Herr, (Hid, Ptr{Cvoid}, Ptr{Cvoid}),
error_stack, old_func[], old_client_data[])
res
h5e_set_auto(error_stack, old_func[], old_client_data[])
return res
end

# Define globally because JLD uses this, too
Expand Down
42 changes: 42 additions & 0 deletions src/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@ function h5_dont_atexit()
return nothing
end

function h5_free_memory(buf)
var"#status#" = ccall((:H5free_memory, libhdf5), Herr, (Ptr{Cvoid},), buf)
var"#status#" < 0 && error("Error freeing memory")
return nothing
end

function h5_garbage_collect()
var"#status#" = ccall((:H5garbage_collect, libhdf5), Herr, ())
var"#status#" < 0 && error("Error on garbage collect")
return nothing
end

function h5_get_libversion(majnum, minnum, relnum)
var"#status#" = ccall((:H5get_libversion, libhdf5), Herr, (Ref{Cuint}, Ref{Cuint}, Ref{Cuint}), majnum, minnum, relnum)
var"#status#" < 0 && error("Error getting HDF5 library version")
return nothing
end

function h5_open()
var"#status#" = ccall((:H5open, libhdf5), Herr, ())
var"#status#" < 0 && error("Error initializing the HDF5 library")
Expand Down Expand Up @@ -219,6 +231,12 @@ function h5d_write(dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_pl
return nothing
end

function h5e_get_auto(estack_id, func, client_data)
var"#status#" = ccall((:H5Eget_auto2, libhdf5), Herr, (Hid, Ref{Ptr{Cvoid}}, Ref{Ptr{Cvoid}}), estack_id, func, client_data)
var"#status#" < 0 && error("Error getting error reporting behavior")
return nothing
end

function h5e_set_auto(estack_id, func, client_data)
var"#status#" = ccall((:H5Eset_auto2, libhdf5), Herr, (Hid, Ptr{Cvoid}, Ptr{Cvoid}), estack_id, func, client_data)
var"#status#" < 0 && error("Error setting error reporting behavior")
Expand Down Expand Up @@ -267,6 +285,18 @@ function h5f_get_name(obj_id, buf, buf_size)
return var"#status#"
end

function h5f_get_obj_count(file_id, types)
var"#status#" = ccall((:H5Fget_obj_count, libhdf5), Cssize_t, (Hid, Cuint), file_id, types)
var"#status#" < 0 && error("Error getting object count")
return var"#status#"
end

function h5f_get_obj_ids(file_id, types, max_objs, obj_id_list)
var"#status#" = ccall((:H5Fget_obj_ids, libhdf5), Cssize_t, (Hid, Cuint, Csize_t, Ptr{Hid}), file_id, types, max_objs, obj_id_list)
var"#status#" < 0 && error("Error getting objects")
return var"#status#"
end

function h5f_get_vfd_handle(file_id, fapl_id, file_handle)
var"#status#" = ccall((:H5Fget_vfd_handle, libhdf5), Herr, (Hid, Hid, Ptr{Ptr{Cint}}), file_id, fapl_id, file_handle)
var"#status#" < 0 && error("Error getting VFD handle")
Expand Down Expand Up @@ -662,6 +692,12 @@ function h5r_create(ref, loc_id, pathname, ref_type, space_id)
return nothing
end

function h5r_dereference(obj_id, ref_type, ref)
var"#status#" = ccall((:H5Rdereference1, libhdf5), Hid, (Hid, Cint, Ref{HDF5ReferenceObj}), obj_id, ref_type, ref)
var"#status#" < 0 && error("Error dereferencing object")
return var"#status#"
end

function h5r_get_obj_type(loc_id, ref_type, ref, obj_type)
var"#status#" = ccall((:H5Rget_obj_type2, libhdf5), Herr, (Hid, Cint, Ptr{Cvoid}, Ptr{Cint}), loc_id, ref_type, ref, obj_type)
var"#status#" < 0 && error("Error getting object type")
Expand Down Expand Up @@ -913,6 +949,12 @@ function h5do_write_chunk(dset_id, dxpl_id, filter_mask, offset, bufsize, buf)
return nothing
end

function h5lt_dtype_to_text(datatype, str, lang_type, len)
var"#status#" = ccall((:H5LTdtype_to_text, libhdf5_hl), Herr, (Hid, Ptr{UInt8}, Cint, Ref{Csize_t}), datatype, str, lang_type, len)
var"#status#" < 0 && error("Error getting datatype text representation")
return nothing
end

function h5tb_get_field_info(loc_id, table_name, field_names, field_sizes, field_offsets, type_size)
var"#status#" = ccall((:H5TBget_field_info, libhdf5_hl), Herr, (Hid, Ptr{UInt8}, Ptr{Ptr{UInt8}}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}), loc_id, table_name, field_names, field_sizes, field_offsets, type_size)
var"#status#" < 0 && error("Error getting field information")
Expand Down