C# 如何使用HDF5DOTNET创建复合数据类型?

C# 如何使用HDF5DOTNET创建复合数据类型?,c#,hdf5,hdf5dotnet,C#,Hdf5,Hdf5dotnet,我在将包含数组的结构写入HDF5数据集中时遇到问题。首先,窗口窗体不以行开头: H5T.insert(typeStruct,“string”,0,H5T.create_数组(新的H5DataTypeId(H5T.H5Type.C_S1),dims2)) 窗口窗体至少在没有行的情况下启动,因此我认为定义复合数据类型有问题。我已经查阅了手册和许多示例,但仍然无法解决这些问题。我能举一个使用复合数据类型在C#中编写具有多个数组的结构的例子吗 使用HDF5DotNet; 利用制度全球化; 使用Syste

我在将包含数组的结构写入HDF5数据集中时遇到问题。首先,窗口窗体不以行开头:

H5T.insert(typeStruct,“string”,0,H5T.create_数组(新的H5DataTypeId(H5T.H5Type.C_S1),dims2))

窗口窗体至少在没有行的情况下启动,因此我认为定义复合数据类型有问题。我已经查阅了手册和许多示例,但仍然无法解决这些问题。我能举一个使用复合数据类型在C#中编写具有多个数组的结构的例子吗

使用HDF5DotNet;
利用制度全球化;
使用System.IO;
使用System.Runtime.InteropServices;
运用系统反思;
命名空间Windows窗体应用程序1
{
公共不安全部分类Form1:Form
{
公共不安全结构
{
公共字符串[]arr_currentLong;
公共结构\u TR(字节大小\u当前时间)
{
arr_currentLong=新字符串[size_currentTime];
}
}
公共表格1()
{
初始化组件();
长数组_SIZE=255;
struct_TR structmake=new struct_TR(255);
对于(int i=0;i<255;i++)
{
structmake.arr_currentLong[i]=i.ToString();
}
字符串currentPath=Path.GetDirectoryName(Application.ExecutablePath);
目录.SetCurrentDirectory(currentPath);
H5FileId fileId=H5F.create(@“weights.h5”,H5F.CreateMode.ACC_TRUNC);
长[]dims1={1};
long[]dims2={1,数组_SIZE};
H5DataSpaceId myDataSpace=H5S.create_simple(1,dims1);
H5DataTypeId string_type=H5T.copy(H5T.H5Type.C_S1);
H5DataTypeId数组_tid1=H5T.创建数组(字符串类型,dims2);
H5DataTypeId typeStruct=H5T.create(H5T.CreateClass.component,Marshal.SizeOf(typeof(struct_TR));
H5T.insert(typeStruct,“string”,0,H5T.create_数组(新的H5DataTypeId(H5T.H5Type.C_S1),dims2));
H5DataSetId myDataSet=H5D.create(fileId,“/dset”,typeStruct,myDataSpace);
H5D.writeScalar(myDataSet、typeStruct、ref StructMake);
}
}
}

我知道如何使用数组保存结构的唯一方法是创建一个常量数组 例如,这是一个数组长度为4的结构

    [StructLayout(LayoutKind.Sequential)]
    public struct Responses
    {
        public Int64 MCID;
        public int PanelIdx;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public short[] ResponseValues;
    }
此处创建了包含数组的4个结构的数组:

       responseList = new Responses[4] {
            new Responses() { MCID=1,PanelIdx=5,ResponseValues=new short[4]{ 1,2,3,4} },
            new Responses() { MCID=2,PanelIdx=6,ResponseValues=new short[4]{ 5,6,7,8}},
            new Responses() { MCID=3,PanelIdx=7,ResponseValues=new short[4]{ 1,2,3,4}},
            new Responses() { MCID=4,PanelIdx=8,ResponseValues=new short[4]{ 5,6,7,8}}
        };
以下代码行将结构数组写入HDF5文件:

        string filename = "testArrayCompounds.H5";
        var fileId =H5F.create(filename, H5F.ACC_TRUNC);
        var status = WriteCompounds(fileId, "/test", responseList);
        H5F.close(fileId);
WriteCompounds方法如下所示:

    public static int WriteCompounds<T>(hid_t groupId, string name, IEnumerable<T> list) //where T : struct
    {
        Type type = typeof(T);
        var size = Marshal.SizeOf(type);
        var cnt = list.Count();

        var typeId = CreateType(type);

        var log10 = (int)Math.Log10(cnt);
        ulong pow = (ulong)Math.Pow(10, log10);
        ulong c_s = Math.Min(1000, pow);
        ulong[] chunk_size = new ulong[] { c_s };

        ulong[] dims = new ulong[] { (ulong)cnt };

        long dcpl = 0;
        if (!list.Any() || log10 == 0) { }
        else
        {
            dcpl = CreateProperty(chunk_size);
        }

        // Create dataspace.  Setting maximum size to NULL sets the maximum
        // size to be the current size.
        var spaceId = H5S.create_simple(dims.Length, dims, null);

        // Create the dataset and write the compound data to it.
        var datasetId = H5D.create(groupId, name, typeId, spaceId, H5P.DEFAULT, dcpl);

        IntPtr p = Marshal.AllocHGlobal(size * (int)dims[0]);

        var ms = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(ms);
        foreach (var strct in list)
            writer.Write(getBytes(strct));
        var bytes = ms.ToArray();

        GCHandle hnd = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        var statusId = H5D.write(datasetId, typeId, spaceId, H5S.ALL,
            H5P.DEFAULT, hnd.AddrOfPinnedObject());

        hnd.Free();
        /*
         * Close and release resources.
         */
        H5D.close(datasetId);
        H5S.close(spaceId);
        H5T.close(typeId);
        H5P.close(dcpl);
        Marshal.FreeHGlobal(p);
        return statusId;
    }
我还有一个ReadComponents来读取hdf5文件。CreateType方法中使用的Hdf5.GetCompoundInfo方法也很长。所以我在这里不展示这些方法

因此,仅仅为了编写一些结构,就需要编写大量的代码。 我创建了一个名为的库,它允许您更轻松地读写类和结构。在那里,您还可以找到ReadComponents和GetCompoundInfo方法


在的单元测试中,您还可以找到如何使用数组编写类的示例

感谢您的详细解释和示例代码!我从你的回答中学到了很多!
    public static int WriteCompounds<T>(hid_t groupId, string name, IEnumerable<T> list) //where T : struct
    {
        Type type = typeof(T);
        var size = Marshal.SizeOf(type);
        var cnt = list.Count();

        var typeId = CreateType(type);

        var log10 = (int)Math.Log10(cnt);
        ulong pow = (ulong)Math.Pow(10, log10);
        ulong c_s = Math.Min(1000, pow);
        ulong[] chunk_size = new ulong[] { c_s };

        ulong[] dims = new ulong[] { (ulong)cnt };

        long dcpl = 0;
        if (!list.Any() || log10 == 0) { }
        else
        {
            dcpl = CreateProperty(chunk_size);
        }

        // Create dataspace.  Setting maximum size to NULL sets the maximum
        // size to be the current size.
        var spaceId = H5S.create_simple(dims.Length, dims, null);

        // Create the dataset and write the compound data to it.
        var datasetId = H5D.create(groupId, name, typeId, spaceId, H5P.DEFAULT, dcpl);

        IntPtr p = Marshal.AllocHGlobal(size * (int)dims[0]);

        var ms = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(ms);
        foreach (var strct in list)
            writer.Write(getBytes(strct));
        var bytes = ms.ToArray();

        GCHandle hnd = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        var statusId = H5D.write(datasetId, typeId, spaceId, H5S.ALL,
            H5P.DEFAULT, hnd.AddrOfPinnedObject());

        hnd.Free();
        /*
         * Close and release resources.
         */
        H5D.close(datasetId);
        H5S.close(spaceId);
        H5T.close(typeId);
        H5P.close(dcpl);
        Marshal.FreeHGlobal(p);
        return statusId;
    }
    private static long CreateType(Type t)
    {
        var size = Marshal.SizeOf(t);
        var float_size = Marshal.SizeOf(typeof(float));
        var int_size = Marshal.SizeOf(typeof(int));
        var typeId = H5T.create(H5T.class_t.COMPOUND, new IntPtr(size));

        var compoundInfo = Hdf5.GetCompoundInfo(t);
        foreach (var cmp in compoundInfo)
        {
            H5T.insert(typeId, cmp.name, Marshal.OffsetOf(t, cmp.name), cmp.datatype);
        }
        return typeId;
    }

    private static long CreateProperty(ulong[] chunk_size)
    {
        var dcpl = H5P.create(H5P.DATASET_CREATE);
        H5P.set_layout(dcpl, H5D.layout_t.CHUNKED);
        H5P.set_chunk(dcpl, chunk_size.Length, chunk_size);
        H5P.set_deflate(dcpl, 6);
        return dcpl;
    }