如何使用H5LTget_attribute_string函数?
How to use the H5LTget_attribute_string function?
我已经在 HDF Forum here 上问过这个问题,但(还)没有收到答复。所以我想我在这里碰碰运气。
我在 Python (h5py) 中创建了一个小测试文件,想使用 H5LTget_attribute_string
函数从中读取属性。但是,我不确定如何使用此功能。
我的测试文件是这样的。
HDF5 "attr.h5" {
GROUP "/" {
DATASET "my_dataset" {
DATATYPE H5T_STD_I64LE
DATASPACE SIMPLE { ( 12 ) / ( 12 ) }
DATA {
(0): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
}
ATTRIBUTE "string_attr" {
DATATYPE H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_UTF8;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "this is a string"
}
}
}
}
}
看着 documentation of H5LT_GET_ATTRIBUTE 在我看来,我需要分配一个缓冲区并将缓冲区的地址作为最后一个参数传递,之后 H5LT_GET_ATTRIBUTE 函数将填充缓冲区。因此,我的第一次尝试是这样的。
#include <assert.h>
#include <stdlib.h>
#include "hdf5.h"
#include "hdf5_hl.h"
int main()
{
herr_t status;
hid_t file_id = H5Fopen("attr.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
assert(file_id >= 0);
char string[1024]; // assume buffer is large enough;
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
fprintf(stderr, "---- reading attribute ----\n");
status = H5LTget_attribute_string(file_id, "my_dataset",
"string_attr", string);
assert(status >= 0);
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
status = H5Fclose(file_id);
assert(status >= 0);
}
然而这并没有像预期的那样工作,请看下面的输出。
string :
pointer: 0x7ffe3f7ec770
---- reading attribute ----
string : @B�k2V
pointer: 0x7ffe3f7ec770
经过一些谷歌搜索和试验,我发现最后一个参数应该是缓冲区的地址。然后 H5LT_GET_ATTRIBUTE 函数将使缓冲区指向实际的属性值。以下函数编译时出现警告,但它给出了正确的输出。
#include <assert.h>
#include <stdlib.h>
#include "hdf5.h"
#include "hdf5_hl.h"
int main()
{
herr_t status;
hid_t file_id = H5Fopen("attr.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
assert(file_id >= 0);
char* string = NULL;
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
fprintf(stderr, "---- reading attribute ----\n");
status = H5LTget_attribute_string(file_id, "my_dataset",
"string_attr", &string);
assert(status >= 0);
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
status = H5Fclose(file_id);
assert(status >= 0);
}
输出
string : (null)
pointer: (nil)
---- reading attribute ----
string : this is a string
pointer: 0x559e9e3d1240
现在我非常乐意像这样使用它,我可以转换为 **char
来摆脱警告,但我想确保这是预期的行为。理想情况下,应该更新文档。
所以我的问题是:
- 第二个例子是否正确?
string
缓冲区的数据有效期是多久?即HDF lib什么时候释放内存? (例如,当文件关闭时)
- 在使用之前是否应该使用
strcpy
复制字符串数据?
我不做 HDF5,但我做的 C 足够多,可以为您提供一些答案,并且非常符合您的要求。
- 第二个例子是否正确?
是的。首先是因为它 returns 是正确的预期结果,其次
因为任何将填充字符串(又名:char *
)的库都需要您提供指针的地址(又名:char **
)。
string
缓冲区的数据有效期是多久?
只要你的程序运行就有效。已为您分配了大小合适的内存,因此它在程序的整个生命周期内都有效,但是现在您有责任释放它。
如果您需要更多详细信息,请 respond/comment 在该消息中说明,我们会帮助您。
- 在使用之前是否应该使用
strcpy
复制字符串数据?
不,你没有为你分配内存,你可以保持原样:-)
我建议你做的下一步:
- 既然您在他们的文档中发现了问题,您应该联系他们并告诉他们。
如 Scot Breitenfeld(来自 HDF 组)pointed:
If you are reading a variable length string with H5LTget_attribute_string (H5T_VARIABLE) then you don’t need to allocate the string, just pass in a pointer and the library will handle the allocations. If you are reading a fixed length string then you need to allocate a string that is “large enough”.
所以,(1) 我觉得你的第二种方法没问题。
至于 (2) 和 (3),我敢打赌你负责释放缓冲区,所以不需要复制它。但是,可以肯定的是,您可以使用调试器来检查库是否正在访问缓冲区,或者更好的是,使用 valgrind
来查找内存泄漏(当您尝试不 free
缓冲区时)。
我已经在 HDF Forum here 上问过这个问题,但(还)没有收到答复。所以我想我在这里碰碰运气。
我在 Python (h5py) 中创建了一个小测试文件,想使用 H5LTget_attribute_string
函数从中读取属性。但是,我不确定如何使用此功能。
我的测试文件是这样的。
HDF5 "attr.h5" {
GROUP "/" {
DATASET "my_dataset" {
DATATYPE H5T_STD_I64LE
DATASPACE SIMPLE { ( 12 ) / ( 12 ) }
DATA {
(0): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
}
ATTRIBUTE "string_attr" {
DATATYPE H5T_STRING {
STRSIZE H5T_VARIABLE;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_UTF8;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "this is a string"
}
}
}
}
}
看着 documentation of H5LT_GET_ATTRIBUTE 在我看来,我需要分配一个缓冲区并将缓冲区的地址作为最后一个参数传递,之后 H5LT_GET_ATTRIBUTE 函数将填充缓冲区。因此,我的第一次尝试是这样的。
#include <assert.h>
#include <stdlib.h>
#include "hdf5.h"
#include "hdf5_hl.h"
int main()
{
herr_t status;
hid_t file_id = H5Fopen("attr.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
assert(file_id >= 0);
char string[1024]; // assume buffer is large enough;
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
fprintf(stderr, "---- reading attribute ----\n");
status = H5LTget_attribute_string(file_id, "my_dataset",
"string_attr", string);
assert(status >= 0);
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
status = H5Fclose(file_id);
assert(status >= 0);
}
然而这并没有像预期的那样工作,请看下面的输出。
string :
pointer: 0x7ffe3f7ec770
---- reading attribute ----
string : @B�k2V
pointer: 0x7ffe3f7ec770
经过一些谷歌搜索和试验,我发现最后一个参数应该是缓冲区的地址。然后 H5LT_GET_ATTRIBUTE 函数将使缓冲区指向实际的属性值。以下函数编译时出现警告,但它给出了正确的输出。
#include <assert.h>
#include <stdlib.h>
#include "hdf5.h"
#include "hdf5_hl.h"
int main()
{
herr_t status;
hid_t file_id = H5Fopen("attr.h5", H5F_ACC_RDONLY, H5P_DEFAULT);
assert(file_id >= 0);
char* string = NULL;
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
fprintf(stderr, "---- reading attribute ----\n");
status = H5LTget_attribute_string(file_id, "my_dataset",
"string_attr", &string);
assert(status >= 0);
fprintf(stderr, "string : %s\n", string);
fprintf(stderr, "pointer: %p\n", string);
status = H5Fclose(file_id);
assert(status >= 0);
}
输出
string : (null)
pointer: (nil)
---- reading attribute ----
string : this is a string
pointer: 0x559e9e3d1240
现在我非常乐意像这样使用它,我可以转换为 **char
来摆脱警告,但我想确保这是预期的行为。理想情况下,应该更新文档。
所以我的问题是:
- 第二个例子是否正确?
string
缓冲区的数据有效期是多久?即HDF lib什么时候释放内存? (例如,当文件关闭时)- 在使用之前是否应该使用
strcpy
复制字符串数据?
我不做 HDF5,但我做的 C 足够多,可以为您提供一些答案,并且非常符合您的要求。
- 第二个例子是否正确?
是的。首先是因为它 returns 是正确的预期结果,其次
因为任何将填充字符串(又名:char *
)的库都需要您提供指针的地址(又名:char **
)。
string
缓冲区的数据有效期是多久?
只要你的程序运行就有效。已为您分配了大小合适的内存,因此它在程序的整个生命周期内都有效,但是现在您有责任释放它。 如果您需要更多详细信息,请 respond/comment 在该消息中说明,我们会帮助您。
- 在使用之前是否应该使用
strcpy
复制字符串数据?
不,你没有为你分配内存,你可以保持原样:-)
我建议你做的下一步:
- 既然您在他们的文档中发现了问题,您应该联系他们并告诉他们。
如 Scot Breitenfeld(来自 HDF 组)pointed:
If you are reading a variable length string with H5LTget_attribute_string (H5T_VARIABLE) then you don’t need to allocate the string, just pass in a pointer and the library will handle the allocations. If you are reading a fixed length string then you need to allocate a string that is “large enough”.
所以,(1) 我觉得你的第二种方法没问题。
至于 (2) 和 (3),我敢打赌你负责释放缓冲区,所以不需要复制它。但是,可以肯定的是,您可以使用调试器来检查库是否正在访问缓冲区,或者更好的是,使用 valgrind
来查找内存泄漏(当您尝试不 free
缓冲区时)。