HDF5:具有可变长度字符串到数据包表的复合数据类型

时间:2021-01-29 20:56:56

标签: c hdf5

我已使用以下代码成功地将固定长度的复合数据类型导出到数据包表:

typedef struct moddata_t {
    char cLog[4096];
} moddata_t;
//  
//  Attempt to open the revision history packet table
hid_t hidPTableID = H5PTopen(hidID, "Revision History");
//
//  Create copy of native character type
hid_t hidCharLen4096TypeID = H5Tcopy(H5T_C_S1);
//
//  Set size of character type
H5Tset_size(hidCharLen4096TypeID, 4096);
//
//  Create memory data type for compound data
hid_t hidModDataTypeID = H5Tcreate(H5T_COMPOUND, sizeof(moddata_t));
H5Tinsert(hidModDataTypeID, "log", HOFFSET(moddata_t, cLog), hidCharLen4096TypeID);
//
//  Create fixed length packet table
hidPTableID = H5PTcreate(hidID, "Revision History", hidModDataTypeID, 1, H5P_DEFAULT);
//
//  Free resources
H5Tclose(hidModDataTypeID);
H5Tclose(hidCharLen4096TypeID);
//
//  Fill data type
//    NOTE:  get() function returns a string with miscellaneous info to be exported to packet table
moddata_t modDat;
strcpy(modDat.cLog, get().c_str());
//
//  Append data to packet table
herr_t herrErr = H5PTappend(hidPTableID, 1, &modDat);
//
//  Close packet table
H5PTclose(hidPTableID);

但是,如果我更改为使用可变长度字符串,则在调用 H5PTappend 时会在 HDF5 内的某处出现段错误。不幸的是,使用数据包表的例子并不多。这是失败的修改后的代码:

typedef struct moddata_t {
    hvl_t cLogHandle;
} moddata_t;
//  
//  Attempt to open the revision history packet table
hid_t hidPTableID = H5PTopen(hidID, "Revision History");
//
//  Create copy of native character type
hid_t hidCharLenVarTypeID = H5Tcopy(H5T_C_S1);
//
//  Set size of character type
H5Tset_size(hidCharLenVarTypeID, H5T_VARIABLE);
//
//  Create memory data type for compound data
hid_t hidModDataTypeID = H5Tcreate(H5T_COMPOUND, sizeof(moddata_t));
H5Tinsert(hidModDataTypeID, "log", HOFFSET(moddata_t, cLogHandle), hidCharLenVarTypeID);
//
//  Create fixed length packet table
hidPTableID = H5PTcreate(hidID, "Revision History", hidModDataTypeID, 1, H5P_DEFAULT);
//
//  Free resources
H5Tclose(hidModDataTypeID);
H5Tclose(hidCharLen4096TypeID);
//
//  Fill data type
//    NOTE:  get() function returns a string with miscellaneous info to be exported to packet table
moddata_t modDat;
modDat.cLogHandle.len = get().length() + 1;   // Added one for \0 character;
modDat.cLogHandle.p = new char [get().length()+1];
strcpy((char *) modDat.cLogHandle.p, get().c_str());
//
//  Append data to packet table
herr_t herrErr = H5PTappend(hidPTableID, 1, &modDat);
//
//  Close packet table
H5PTclose(hidPTableID);

将其他人为声明具有可变长度元素的复合数据类型所做的工作拼凑起来,我认为我正确地创建了数据类型。但是,没有太多定义 hvl_t 结构,所以我不确定我是否正确定义了 lenp 变量和这就是它出现段错误的原因。

感谢任何帮助。

谢谢

2 个答案:

答案 0 :(得分:0)

如果您使用更高级别的 API,例如 HDFql,您可能会更好,因为它以非常简单和直观的方式(从开发人员的角度)处理 HDF5 复合数据集/属性。看一看 HDFql reference manual,您可以在其中获得许多关于如何在 C 中创建、读取和写入复合数据集/属性的示例(除了其他语言,例如 C++、{{1} }、JavaPythonC#R)。

答案 1 :(得分:0)

回答我自己的问题。

如果我删除:

 //
 //  Create copy of native character type
 hid_t hidCharLenVarTypeID = H5Tcopy(H5T_C_S1);
 //
 //  Set size of character type
 H5Tset_size(hidCharLenVarTypeID, H5T_VARIABLE);

并替换为:

 hid_t hidCharLenVarTypeID = H5Tvlen_create(H5T_C_S1);

然后它似乎起作用了。然而,来自这个 https://support.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#CreateVLString,它说:

<块引用>

创建变长字符串数据类型

顾名思义,变长字符串是长度可变的字符串;它们可以是任意长的,从 1 个字符到数千个字符不等。

HDF5 提供了创建可变长度字符串数据类型的能力。与所有字符串数据类型一样,此类型基于原子字符串数据类型:C 中的 H5T_C_S1 或 Fortran 中的 H5T_FORTRAN_S1。虽然这些数据类型的大小默认为一个字符,但它们可以调整为特定的固定长度或可变长度。

可变长度字符串将透明地容纳 ASCII 字符串或 UTF-8 字符串。这个特性是在创建数据类型的过程中通过H5Tset_cset设置的。

以下 HDF5 调用创建了一个 C 风格的可变长度字符串数据类型,vls_type_c_id:

vls_type_c_id = H5Tcopy(H5T_C_S1)  
status = H5Tset_size(vls_type_c_id, H5T_VARIABLE)  
<块引用>

在 C 环境中,变长字符串总是以 NULL 结尾,因此保存此类字符串的缓冲区必须比字符串本身大一个字节以容纳 NULL 终止符。

因此,如何声明可变长度字符串似乎有些混乱。

约翰