带有指针数组的 HDF5 结构
Posted
技术标签:
【中文标题】带有指针数组的 HDF5 结构【英文标题】:HDF5 struct with pointer array 【发布时间】:2013-02-16 14:41:15 【问题描述】:我正在尝试编写一个 HDF5 文件,其结构包含一个 int 和一个 float*
typedef struct s1_t
int a;
float *b;
s1_t;
但是,在分配 float* 并将值放入其中后,我仍然无法在 hdf5 文件中输出数据。我相信这是因为 write 函数假定复合数据类型是连续的,而动态分配的数组不会。有没有办法通过仍然使用指针数组来解决这个问题?
/*
* This example shows how to create a compound data type with an array member,
* and write an array which has the compound data type to the file.
*/
#include "stdio.h"
#include "stdlib.h"
#include "hdf5.h"
#define FILE "DSwith_array_member.h5"
#define DATASETNAME "ArrayOfStructures"
#define LENGTH 10
#define RANK 1
#define ARRAY_RANK 1
#define ARRAY_DIM 3
int
main(void)
/* First structure and dataset*/
typedef struct s1_t
int a;
//float b[ARRAY_DIM];
float *b;
s1_t;
s1_t s1[LENGTH];
hid_t s1_tid; /* File datatype identifier */
hid_t array_tid; /* Array datatype handle */
hid_t file, dataset, space; /* Handles */
herr_t status;
hsize_t dim[] = LENGTH; /* Dataspace dimensions */
hsize_t array_dim[] = ARRAY_DIM; /* Array dimensions */
int i, j;
/*
* Initialize the data
*/
for (i = 0; i< LENGTH; i++)
s1[i].a = i;
s1[i].b = (float*)calloc(ARRAY_DIM, sizeof(float));
for (j = 0; j < ARRAY_DIM; j++)
s1[i].b[j] = i+j;
/*
* Create the data space.
*/
space = H5Screate_simple(RANK, dim, NULL);
/*
* Create the file.
*/
file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
/*
* Create the array data type.
*/
array_tid = H5Tarray_create(H5T_NATIVE_FLOAT, ARRAY_RANK, array_dim);
/*
* Create the memory data type.
*/
s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t));
H5Tinsert(s1_tid, "a_name", HOFFSET(s1_t, a), H5T_NATIVE_INT);
H5Tinsert(s1_tid, "b_name", HOFFSET(s1_t, b), array_tid);
/*
* Create the dataset.
*/
dataset = H5Dcreate(file, DATASETNAME, s1_tid, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
/*
* Wtite data to the dataset;
*/
status = H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1);
/*
* Release resources
*/
H5Tclose(s1_tid);
H5Tclose(array_tid);
H5Sclose(space);
H5Dclose(dataset);
H5Fclose(file);
return 0;
【问题讨论】:
【参考方案1】:你是对的。将结构更改为
typedef struct s1_t
int a;
float b[ARRAY_DIM];
s1_t;
会起作用,但我想你知道这一点。
我可以看到两种解决方案:
-
使用临时缓冲区(如上述结构的数组)进行写入。
使用可变长度数组代替
b_name
的数组。
为b_name
使用可变长度数组的示例
#include "stdio.h"
#include "stdlib.h"
#include "hdf5.h"
#define FILE "DSwith_array_member.h5"
#define DATASETNAME "ArrayOfStructures"
#define LENGTH 10
#define RANK 1
#define ARRAY_RANK 1
#define ARRAY_DIM 3
typedef struct s1_t
int a;
float *b;
s1_t;
typedef struct s1_buffer_t
int a;
hvl_t b;
s1_buffer_t;
int main(void)
s1_t s1[LENGTH];
hid_t s1_tid; /* File datatype identifier */
hid_t file, dataset, space, vlen_tid; /* Handles */
hsize_t dim[] = LENGTH; /* Dataspace dimensions */
int i, j;
s1_buffer_t s1_buffer[LENGTH];
for (i = 0; i< LENGTH; i++)
s1[i].a = i;
s1[i].b = (float*)calloc(ARRAY_DIM, sizeof(float));
for (j = 0; j < ARRAY_DIM; j++)
s1[i].b[j] = i+j;
space = H5Screate_simple(RANK, dim, NULL);
file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
vlen_tid = H5Tvlen_create(H5T_NATIVE_FLOAT);
s1_tid = H5Tcreate(H5T_COMPOUND, sizeof(s1_buffer_t));
H5Tinsert(s1_tid, "a_name", HOFFSET(s1_t, a), H5T_NATIVE_INT);
H5Tinsert(s1_tid, "b_name", HOFFSET(s1_t, b), vlen_tid);
dataset = H5Dcreate(file, DATASETNAME, s1_tid, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
for (i = 0; i < LENGTH; ++i)
s1_buffer[i].a = s1[i].a;
s1_buffer[i].b.len = ARRAY_DIM;
s1_buffer[i].b.p = s1[i].b;
H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1_buffer);
H5Tclose(s1_tid);
H5Tclose(vlen_tid);
H5Sclose(space);
H5Dclose(dataset);
H5Fclose(file);
return 0;
如您所见,您仍然需要一个临时缓冲区,但至少它只需要存储指针(来自 s1
的 b
指针)而不是大小为 ARRAY_DIM
的数组,就像解决方案 1 的情况一样以上。
【讨论】:
我尝试为 b_name 实现一个变量数组,但是当我尝试调用 H5Dwrite() 时,我一直遇到未处理的异常错误。你能给我一个简单的例子吗? b_name 作为可变长度数组? @foboi1122 我添加了一个例子。 谢谢你的例子,现在我更清楚了。有没有办法将此文件直接读入标准结构?我的意思是当我们调用 H5Dread 时,我读入了一个结构为 s1_buffer_t 的缓冲区,但是,s1_buffer 类型包含一个 hvl_t 类型的数组。在标准数据结构中,我不使用这些类型的数组。它们通常只是浮动数组。所以现在,我正在做一个从 s1_buffer_t 结构到我自己的类似结构的 memcpy,它使用 float *b 而不是 hvl_t b。然而,这最终会占用更多内存,因为我必须持有缓冲区和结构。 我知道,我希望在这种情况下我们可以避免使用临时缓冲区,但似乎不可能。如果您使用 C++,您可以将其封装在一个类中:存储s1_buffer_t
的数组,但公开s1_t
的接口……这实际上取决于您的应用程序在读/写或使用数据之间更关键的是什么.以上是关于带有指针数组的 HDF5 结构的主要内容,如果未能解决你的问题,请参考以下文章
使用带有结构/数组的头文件的指针问题,导致多重定义错误(C)
如何在 C 中将动态分配的 3D 数组写入 hdf5 文件?