diff options
author | Quincey Koziol <koziol@koziol.gov> | 2019-04-21 19:45:54 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@koziol.gov> | 2019-04-21 19:45:54 (GMT) |
commit | 62198c2436ac3787afb49fa990d1ba8204264dba (patch) | |
tree | ce6f47307d75ffa61f49de88fdf72a014adfd1fb /src | |
parent | 500f6cccbd4bfe01b67f2bd02f74df58edef045f (diff) | |
download | hdf5-62198c2436ac3787afb49fa990d1ba8204264dba.zip hdf5-62198c2436ac3787afb49fa990d1ba8204264dba.tar.gz hdf5-62198c2436ac3787afb49fa990d1ba8204264dba.tar.bz2 |
Add an 'unwrap' VOL callback, so that connectors can unwrap an underlying
object without closing it. (Especially needed for pass-through connectors)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Dvirtual.c | 2 | ||||
-rw-r--r-- | src/H5I.c | 2 | ||||
-rw-r--r-- | src/H5VLcallback.c | 165 | ||||
-rw-r--r-- | src/H5VLint.c | 28 | ||||
-rw-r--r-- | src/H5VLnative.c | 1 | ||||
-rw-r--r-- | src/H5VLpassthru.c | 67 | ||||
-rw-r--r-- | src/H5VLprivate.h | 6 | ||||
-rw-r--r-- | src/H5VLpublic.h | 2 |
8 files changed, 213 insertions, 60 deletions
diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index d38df1b..e3e0aa5 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -3035,7 +3035,7 @@ H5D__virtual_refresh_source_dset(H5D_t **dset) /* Discard the identifier & replace the dataset */ if(NULL == (vol_obj = (H5VL_object_t *)H5I_remove(temp_id))) HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "can't unregister source dataset ID") - if(NULL == (*dset = (H5D_t *)H5VL_object_data(vol_obj))) + if(NULL == (*dset = (H5D_t *)H5VL_object_unwrap(vol_obj))) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve library object from VOL object") vol_obj->data = NULL; @@ -1134,7 +1134,7 @@ done: * *------------------------------------------------------------------------- */ -void * +static void * H5I__remove_verify(hid_t id, H5I_type_t id_type) { void * ret_value = NULL; /*return value */ diff --git a/src/H5VLcallback.c b/src/H5VLcallback.c index 03828fa..b785747 100644 --- a/src/H5VLcallback.c +++ b/src/H5VLcallback.c @@ -740,84 +740,89 @@ done: /*------------------------------------------------------------------------- - * Function: H5VL_free_wrap_ctx + * Function: H5VL_wrap_object * - * Purpose: Free object wrapping context for a connector + * Purpose: Wrap an object with connector * - * Return: Success: Non-negative - * Failure: Negative + * Return: Success: Non-NULL + * Failure: NULL * *------------------------------------------------------------------------- */ -herr_t -H5VL_free_wrap_ctx(const H5VL_class_t *connector, void *wrap_ctx) +void * +H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx, void *obj, + H5I_type_t obj_type) { - herr_t ret_value = SUCCEED; /* Return value */ + void *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI(NULL) /* Sanity checks */ HDassert(connector); + HDassert(obj); - /* Only free wrap context, if it's non-NULL */ + /* Only wrap object if there's a wrap context */ if(wrap_ctx) { - /* Free the connector's object wrapping context */ - if((connector->wrap_cls.free_wrap_ctx)(wrap_ctx) < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "connector wrap context free request failed") + /* Ask the connector to wrap the object */ + if(NULL == (ret_value = (connector->wrap_cls.wrap_object)(obj, obj_type, wrap_ctx))) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't wrap object") } /* end if */ + else + ret_value = obj; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL_free_wrap_ctx() */ +} /* end H5VL_wrap_object() */ /*--------------------------------------------------------------------------- - * Function: H5VLfree_wrap_ctx + * Function: H5VLwrap_object * - * Purpose: Release a VOL connector's object wrapping context + * Purpose: Asks a connector to wrap an underlying object. * - * Return: Success: Non-negative - * Failure: Negative + * Return: Success: Non-NULL + * Failure: NULL * *--------------------------------------------------------------------------- */ -herr_t -H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id) +void * +H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, void *wrap_ctx) { - H5VL_class_t *cls; /* VOL connector's class struct */ - herr_t ret_value = SUCCEED; /* Return value */ + H5VL_class_t *cls; /* VOL connector's class struct */ + void *ret_value = NULL; /* Return value */ FUNC_ENTER_API_NOINIT - H5TRACE2("e", "*xi", wrap_ctx, connector_id); + H5TRACE4("*x", "*xIti*x", obj, obj_type, connector_id, wrap_ctx); /* Check args and get class pointer */ + if(NULL == obj) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid object") if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID") - /* Release the VOL connector's object wrapper */ - if(H5VL_free_wrap_ctx(cls, wrap_ctx) < 0) - HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector object wrap context") + /* Wrap the object */ + if(NULL == (ret_value = H5VL_wrap_object(cls, wrap_ctx, obj, obj_type))) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to wrap object") done: FUNC_LEAVE_API_NOINIT(ret_value) -} /* H5VLfree_wrap_ctx() */ +} /* H5VLwrap_object */ /*------------------------------------------------------------------------- - * Function: H5VL_wrap_object + * Function: H5VL_unwrap_object * - * Purpose: Wrap an object with connector + * Purpose: Unwrap an object from connector * - * Return: Success: Non-negative - * Failure: Negative + * Return: Success: Non-NULL + * Failure: NULL * *------------------------------------------------------------------------- */ void * -H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx, void *obj, - H5I_type_t obj_type) +H5VL_unwrap_object(const H5VL_class_t *connector, void *obj) { - void *ret_value = SUCCEED; /* Return value */ + void *ret_value; /* Return value */ FUNC_ENTER_NOAPI(NULL) @@ -825,24 +830,24 @@ H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx, void *obj, HDassert(connector); HDassert(obj); - /* Only wrap object if there's a wrap context */ - if(wrap_ctx) { - /* Ask the connector to wrap the object */ - if(NULL == (ret_value = (connector->wrap_cls.wrap_object)(obj, obj_type, wrap_ctx))) - HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't wrap object") + /* Only unwrap object if there's an unwrap callback */ + if(connector->wrap_cls.wrap_object) { + /* Ask the connector to unwrap the object */ + if(NULL == (ret_value = (connector->wrap_cls.unwrap_object)(obj))) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't unwrap object") } /* end if */ else ret_value = obj; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5VL_wrap_object() */ +} /* end H5VL_unwrap_object() */ /*--------------------------------------------------------------------------- - * Function: H5VLwrap_object + * Function: H5VLunwrap_object * - * Purpose: Asks a connector to wrap an underlying object. + * Purpose: Unwrap an object from connector * * Return: Success: Non-NULL * Failure: NULL @@ -850,13 +855,13 @@ done: *--------------------------------------------------------------------------- */ void * -H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, void *wrap_ctx) +H5VLunwrap_object(void *obj, hid_t connector_id) { H5VL_class_t *cls; /* VOL connector's class struct */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_API_NOINIT - H5TRACE4("*x", "*xIti*x", obj, obj_type, connector_id, wrap_ctx); + H5TRACE2("*x", "*xi", obj, connector_id); /* Check args and get class pointer */ if(NULL == obj) @@ -864,13 +869,77 @@ H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, void *wrap_c if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a VOL connector ID") - /* Wrap the object */ - if(NULL == (ret_value = H5VL_wrap_object(cls, wrap_ctx, obj, obj_type))) - HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to wrap object") + /* Unwrap the object */ + if(NULL == (ret_value = H5VL_unwrap_object(cls, obj))) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "unable to unwrap object") done: FUNC_LEAVE_API_NOINIT(ret_value) -} /* H5VLwrap_object */ +} /* H5VLunwrap_object */ + + +/*------------------------------------------------------------------------- + * Function: H5VL_free_wrap_ctx + * + * Purpose: Free object wrapping context for a connector + * + * Return: Success: Non-negative + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +herr_t +H5VL_free_wrap_ctx(const H5VL_class_t *connector, void *wrap_ctx) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(connector); + + /* Only free wrap context, if it's non-NULL */ + if(wrap_ctx) { + /* Free the connector's object wrapping context */ + if((connector->wrap_cls.free_wrap_ctx)(wrap_ctx) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "connector wrap context free request failed") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_free_wrap_ctx() */ + + +/*--------------------------------------------------------------------------- + * Function: H5VLfree_wrap_ctx + * + * Purpose: Release a VOL connector's object wrapping context + * + * Return: Success: Non-negative + * Failure: Negative + * + *--------------------------------------------------------------------------- + */ +herr_t +H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id) +{ + H5VL_class_t *cls; /* VOL connector's class struct */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API_NOINIT + H5TRACE2("e", "*xi", wrap_ctx, connector_id); + + /* Check args and get class pointer */ + if(NULL == (cls = (H5VL_class_t *)H5I_object_verify(connector_id, H5I_VOL))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a VOL connector ID") + + /* Release the VOL connector's object wrapper */ + if(H5VL_free_wrap_ctx(cls, wrap_ctx) < 0) + HGOTO_ERROR(H5E_VOL, H5E_CANTRELEASE, FAIL, "unable to release VOL connector object wrap context") + +done: + FUNC_LEAVE_API_NOINIT(ret_value) +} /* H5VLfree_wrap_ctx() */ /*------------------------------------------------------------------------- diff --git a/src/H5VLint.c b/src/H5VLint.c index fda4443..1b735f5 100644 --- a/src/H5VLint.c +++ b/src/H5VLint.c @@ -1358,6 +1358,32 @@ H5VL_object_data(const H5VL_object_t *vol_obj) /*------------------------------------------------------------------------- + * Function: H5VL_object_unwrap + * + * Purpose: Correctly unwrap the 'data' field for a VOL object (H5VL_object), + * even for nested / stacked VOL connectors. + * + * Return: Success: Object pointer + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +void * +H5VL_object_unwrap(const H5VL_object_t *vol_obj) +{ + void *ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL) + + if(NULL == (ret_value = H5VL_unwrap_object(vol_obj->connector->cls, vol_obj->data))) + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't unwrap object") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5VL_object_unwrap() */ + + +/*------------------------------------------------------------------------- * Function: H5VL__object * * Purpose: Internal function to return the VOL object pointer associated @@ -1444,7 +1470,7 @@ H5VL_object(hid_t id) /* Get the underlying object */ if(NULL == (ret_value = H5VL__object(id, H5I_get_type(id)))) - HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, NULL, "can't retrieve object for ID") + HGOTO_ERROR(H5E_VOL, H5E_CANTGET, NULL, "can't retrieve object for ID") done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5VLnative.c b/src/H5VLnative.c index f4f3b5f..7848c5d 100644 --- a/src/H5VLnative.c +++ b/src/H5VLnative.c @@ -50,6 +50,7 @@ static H5VL_class_t H5VL_native_cls_g = { NULL, /* get_object */ NULL, /* get_wrap_ctx */ NULL, /* wrap_object */ + NULL, /* unwrap_object */ NULL /* free_wrap_ctx */ }, { /* attribute_cls */ diff --git a/src/H5VLpassthru.c b/src/H5VLpassthru.c index a4c85cc..85a9346 100644 --- a/src/H5VLpassthru.c +++ b/src/H5VLpassthru.c @@ -98,9 +98,10 @@ static herr_t H5VL_pass_through_str_to_info(const char *str, void **info); /* VOL object wrap / retrieval callbacks */ static void *H5VL_pass_through_get_object(const void *obj); static herr_t H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx); -static herr_t H5VL_pass_through_free_wrap_ctx(void *obj); static void *H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type, void *wrap_ctx); +static void *H5VL_pass_through_unwrap_object(void *obj); +static herr_t H5VL_pass_through_free_wrap_ctx(void *obj); /* Attribute callbacks */ static void *H5VL_pass_through_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name, hid_t acpl_id, hid_t aapl_id, hid_t dxpl_id, void **req); @@ -194,6 +195,7 @@ static const H5VL_class_t H5VL_pass_through_g = { H5VL_pass_through_get_object, /* get_object */ H5VL_pass_through_get_wrap_ctx, /* get_wrap_ctx */ H5VL_pass_through_wrap_object, /* wrap_object */ + H5VL_pass_through_unwrap_object, /* unwrap_object */ H5VL_pass_through_free_wrap_ctx, /* free_wrap_ctx */ }, { /* attribute_cls */ @@ -683,8 +685,8 @@ H5VL_pass_through_get_wrap_ctx(const void *obj, void **wrap_ctx) * * Purpose: Use a "wrapper context" to wrap a data object * - * Return: Success: 0 - * Failure: -1 + * Return: Success: Pointer to wrapped object + * Failure: NULL * *--------------------------------------------------------------------------- */ @@ -711,6 +713,37 @@ H5VL_pass_through_wrap_object(void *obj, H5I_type_t obj_type, void *_wrap_ctx) /*--------------------------------------------------------------------------- + * Function: H5VL_pass_through_unwrap_object + * + * Purpose: Unwrap a wrapped object, discarding the wrapper, but returning + * underlying object. + * + * Return: Success: Pointer to unwrapped object + * Failure: NULL + * + *--------------------------------------------------------------------------- + */ +static void * +H5VL_pass_through_unwrap_object(void *obj) +{ + H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + void *under; + +#ifdef ENABLE_PASSTHRU_LOGGING + printf("------- PASS THROUGH VOL UNWRAP Object\n"); +#endif + + /* Unrap the object with the underlying VOL */ + under = H5VLunwrap_object(o->under_object, o->under_vol_id); + + if(under) + H5VL_pass_through_free_obj(o); + + return under; +} /* end H5VL_pass_through_unwrap_object() */ + + +/*--------------------------------------------------------------------------- * Function: H5VL_pass_through_free_wrap_ctx * * Purpose: Release a "wrapper context" for an object @@ -1194,17 +1227,22 @@ H5VL_pass_through_dataset_specific(void *obj, H5VL_dataset_specific_t specific_t hid_t dxpl_id, void **req, va_list arguments) { H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + hid_t under_vol_id; herr_t ret_value; #ifdef ENABLE_PASSTHRU_LOGGING printf("------- PASS THROUGH VOL H5Dspecific\n"); #endif + // Save copy of underlying VOL connector ID and prov helper, in case of + // refresh destroying the current object + under_vol_id = o->under_vol_id; + ret_value = H5VLdataset_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); /* Check for async request */ if(req && *req) - *req = H5VL_pass_through_new_obj(*req, o->under_vol_id); + *req = H5VL_pass_through_new_obj(*req, under_vol_id); return ret_value; } /* end H5VL_pass_through_dataset_specific() */ @@ -1396,17 +1434,22 @@ H5VL_pass_through_datatype_specific(void *obj, H5VL_datatype_specific_t specific hid_t dxpl_id, void **req, va_list arguments) { H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + hid_t under_vol_id; herr_t ret_value; #ifdef ENABLE_PASSTHRU_LOGGING printf("------- PASS THROUGH VOL DATATYPE Specific\n"); #endif + // Save copy of underlying VOL connector ID and prov helper, in case of + // refresh destroying the current object + under_vol_id = o->under_vol_id; + ret_value = H5VLdatatype_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); /* Check for async request */ if(req && *req) - *req = H5VL_pass_through_new_obj(*req, o->under_vol_id); + *req = H5VL_pass_through_new_obj(*req, under_vol_id); return ret_value; } /* end H5VL_pass_through_datatype_specific() */ @@ -1936,17 +1979,22 @@ H5VL_pass_through_group_specific(void *obj, H5VL_group_specific_t specific_type, hid_t dxpl_id, void **req, va_list arguments) { H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + hid_t under_vol_id; herr_t ret_value; #ifdef ENABLE_PASSTHRU_LOGGING printf("------- PASS THROUGH VOL GROUP Specific\n"); #endif + // Save copy of underlying VOL connector ID and prov helper, in case of + // refresh destroying the current object + under_vol_id = o->under_vol_id; + ret_value = H5VLgroup_specific(o->under_object, o->under_vol_id, specific_type, dxpl_id, req, arguments); /* Check for async request */ if(req && *req) - *req = H5VL_pass_through_new_obj(*req, o->under_vol_id); + *req = H5VL_pass_through_new_obj(*req, under_vol_id); return ret_value; } /* end H5VL_pass_through_group_specific() */ @@ -2372,17 +2420,22 @@ H5VL_pass_through_object_specific(void *obj, const H5VL_loc_params_t *loc_params va_list arguments) { H5VL_pass_through_t *o = (H5VL_pass_through_t *)obj; + hid_t under_vol_id; herr_t ret_value; #ifdef ENABLE_PASSTHRU_LOGGING printf("------- PASS THROUGH VOL OBJECT Specific\n"); #endif + // Save copy of underlying VOL connector ID and prov helper, in case of + // refresh destroying the current object + under_vol_id = o->under_vol_id; + ret_value = H5VLobject_specific(o->under_object, loc_params, o->under_vol_id, specific_type, dxpl_id, req, arguments); /* Check for async request */ if(req && *req) - *req = H5VL_pass_through_new_obj(*req, o->under_vol_id); + *req = H5VL_pass_through_new_obj(*req, under_vol_id); return ret_value; } /* end H5VL_pass_through_object_specific() */ diff --git a/src/H5VLprivate.h b/src/H5VLprivate.h index dc4f9c5..04cc982 100644 --- a/src/H5VLprivate.h +++ b/src/H5VLprivate.h @@ -86,6 +86,7 @@ H5_DLL hid_t H5VL_register_connector(const void *cls, hbool_t app_ref, hid_t vip /* Functions that manipulate VOL objects */ H5_DLL void *H5VL_object(hid_t id); H5_DLL void *H5VL_object_data(const H5VL_object_t *vol_obj); +H5_DLL void *H5VL_object_unwrap(const H5VL_object_t *vol_obj); H5_DLL void *H5VL_object_verify(hid_t id, H5I_type_t obj_type); H5_DLL H5VL_object_t *H5VL_vol_object(hid_t id); H5_DLL herr_t H5VL_free_object(H5VL_object_t *obj); @@ -93,13 +94,14 @@ H5_DLL herr_t H5VL_free_object(H5VL_object_t *obj); /* Functions that wrap / unwrap VOL objects */ H5_DLL herr_t H5VL_get_wrap_ctx(const H5VL_class_t *connector, void *obj, void **wrap_ctx); +H5_DLL void * H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx, + void *obj, H5I_type_t obj_type); +H5_DLL void * H5VL_unwrap_object(const H5VL_class_t *connector, void *obj); H5_DLL herr_t H5VL_free_wrap_ctx(const H5VL_class_t *connector, void *wrap_ctx); H5_DLL herr_t H5VL_set_vol_wrapper(void *obj, H5VL_t *vol_connector); H5_DLL herr_t H5VL_inc_vol_wrapper(void *vol_wrap_ctx); H5_DLL herr_t H5VL_dec_vol_wrapper(void *vol_wrap_ctx); H5_DLL herr_t H5VL_reset_vol_wrapper(void); -H5_DLL void * H5VL_wrap_object(const H5VL_class_t *connector, void *wrap_ctx, - void *obj, H5I_type_t obj_type); /* Library state functions */ H5_DLL herr_t H5VL_retrieve_lib_state(void **state); diff --git a/src/H5VLpublic.h b/src/H5VLpublic.h index da31a97..56e703c 100644 --- a/src/H5VLpublic.h +++ b/src/H5VLpublic.h @@ -253,6 +253,7 @@ typedef struct H5VL_wrap_class_t { void * (*get_object)(const void *obj); /* Callback to retrieve underlying object */ herr_t (*get_wrap_ctx)(const void *obj, void **wrap_ctx); /* Callback to retrieve the object wrapping context for the connector */ void * (*wrap_object)(void *obj, H5I_type_t obj_type, void *wrap_ctx); /* Callback to wrap a library object */ + void * (*unwrap_object)(void *obj); /* Callback to unwrap a library object */ herr_t (*free_wrap_ctx)(void *wrap_ctx); /* Callback to release the object wrapping context for the connector */ } H5VL_wrap_class_t; @@ -472,6 +473,7 @@ H5_DLL void *H5VLget_object(void *obj, hid_t connector_id); H5_DLL herr_t H5VLget_wrap_ctx(void *obj, hid_t connector_id, void **wrap_ctx); H5_DLL void *H5VLwrap_object(void *obj, H5I_type_t obj_type, hid_t connector_id, void *wrap_ctx); +H5_DLL void *H5VLunwrap_object(void *obj, hid_t connector_id); H5_DLL herr_t H5VLfree_wrap_ctx(void *wrap_ctx, hid_t connector_id); /* Public wrappers for attribute callbacks */ |