C# 使用hdf5.net读取和写入引用类型

C# 使用hdf5.net读取和写入引用类型,c#,hdf5,C#,Hdf5,我正在使用编写一个通用的数据记录API,DataLog。其思想是使用反射自动创建H5复合数据类型,其中包含T中的字段。然后,用户可以使用write(T[]data)方法轻松地将数据添加到数据日志中 为了自动创建H5类型,必须用[StructLayoutAttribute]修饰类或结构,并用[MarshalAsAttribute]修饰某些字段。然后将每个字段映射到H5类型并添加到H5复合数据类型。包含枚举或其他用户定义结构的类型稍微复杂一点,但它们仍然有效 从我在web上找到的示例中,我成功地创建

我正在使用编写一个通用的数据记录API,
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。