C# 使用hdf5.net读取和写入引用类型
我正在使用编写一个通用的数据记录API,C# 使用hdf5.net读取和写入引用类型,c#,hdf5,C#,Hdf5,我正在使用编写一个通用的数据记录API,DataLog。其思想是使用反射自动创建H5复合数据类型,其中包含T中的字段。然后,用户可以使用write(T[]data)方法轻松地将数据添加到数据日志中 为了自动创建H5类型,必须用[StructLayoutAttribute]修饰类或结构,并用[MarshalAsAttribute]修饰某些字段。然后将每个字段映射到H5类型并添加到H5复合数据类型。包含枚举或其他用户定义结构的类型稍微复杂一点,但它们仍然有效 从我在web上找到的示例中,我成功地创建
DataLog
。其思想是使用反射自动创建H5复合数据类型,其中包含T
中的字段。然后,用户可以使用write(T[]data)
方法轻松地将数据添加到数据日志中
为了自动创建H5类型,必须用[StructLayoutAttribute]
修饰类或结构,并用[MarshalAsAttribute]
修饰某些字段。然后将每个字段映射到H5类型并添加到H5复合数据类型。包含枚举或其他用户定义结构的类型稍微复杂一点,但它们仍然有效
从我在web上找到的示例中,我成功地创建了H5类型,创建了一个数据集,并为我创建的简单结构添加了一些数据
当我将类型从struct
更改为class
时,就会出现问题。H5Type仍然被创建,没有抛出异常,但是当我在中打开文件时,我可以看到正确的字段,但是数据是垃圾
我怀疑出现这个问题是因为在C#中,结构是值类型,类是引用类型。我使用以下代码来确定数据的底层结构:
public static byte[] GetBytes(dynamic obj)
{
var size = Marshal.SizeOf(obj);
// Both managed and unmanaged buffers required.
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
// Copy object byte-to-byte to unmanaged memory.
Marshal.StructureToPtr(obj, ptr, false);
// Copy data from unmanaged memory to managed buffer.
Marshal.Copy(ptr, bytes, 0, size);
// Release unmanaged memory.
Marshal.FreeHGlobal(ptr);
return bytes;
}
事实证明,无论我使用的是类还是结构,这个函数的字节数和它们的顺序都是一样的
作为参考(而且因为web上没有太多代码示例),我将提供我的代码以附加到现有数据集:
public static void AppendToDataSet<DataType>(H5DataSetId dataSetId, DataType[] data)
{
if (data.Length < 1)
{
return;
}
var dataSpaceId = H5D.getSpace(dataSetId);
var rank = H5S.getSimpleExtentNDims(dataSpaceId);
var dims = H5S.getSimpleExtentDims(dataSpaceId);
var rank_chunk = new long[] { };
var prop = H5D.getCreatePropertyList(dataSetId);
if (H5P.getLayout(prop) == H5D.Layout.CHUNKED)
{
rank_chunk = H5P.getChunk(prop, rank);
}
var dims_extended = new long[] { dims[0] + data.Length }; // the new data set size
/* Extend the dataset */
H5D.setExtent(dataSetId, dims_extended);
/* Select a hyperslab in extended portion of dataset */
H5S.selectHyperslab(dataSpaceId, H5S.SelectOperator.SET, new long[] { dims[0] }, new long[] { data.Length });
/* Define memory space */
var memspace = H5S.create_simple(rank, dims_extended);
/* Convert to HDF data */
var hdf_data = new H5Array<DataType>(data);
/* Write the data to the extended portion of dataset */
var dataTypeId = H5D.getType(dataSetId);
H5D.write(dataSetId,
dataTypeId,
hdf_data);
}
publicstaticvoidappendtodataset(H5DataSetId-dataSetId,DataType[]data)
{
如果(数据长度<1)
{
返回;
}
var dataSpaceId=H5D.getSpace(dataSetId);
var rank=H5S.getSimpleExtentNDims(dataSpaceId);
var dims=H5S.getSimpleExtentDims(数据空间ID);
var rank_chunk=new long[]{};
var prop=H5D.getCreatePropertyList(dataSetId);
if(H5P.getLayout(prop)=H5D.Layout.CHUNKED)
{
rank_chunk=H5P.getChunk(prop,rank);
}
var dims_extended=new long[]{dims[0]+data.Length};//新的数据集大小
/*扩展数据集*/
H5D.设置范围(数据集,dims_扩展);
/*在数据集的扩展部分中选择hyperslab*/
H5S.selectHyperslab(dataSpaceId,H5S.SelectOperator.SET,新长[]{dims[0]},新长[]{data.Length});
/*定义内存空间*/
var memspace=H5S.create_simple(秩,dims_扩展);
/*转换为HDF数据*/
var hdf_数据=新阵列(数据);
/*将数据写入数据集的扩展部分*/
var dataTypeId=H5D.getType(dataSetId);
H5D.写入(dataSetId,
数据类型ID,
hdf_数据);
}
我希望能够为此使用类,因为使用结构需要对应用程序的其余部分进行重大的结构更改。有人知道为什么H5编写不适用于类,我有什么方法可以解决它吗?对于阅读本文的人,我意识到HDF.PInvoke()已经取代了HDFDotNet。