HDF5DotNet and string in compound data type

I know this question (or related to) has been asked a few times but the answers don't seem to be of any help to me. Below is my code. I am simply trying to write out a compound data type with one element being a string. All the numbers, i.e. int1, double1, and double2 in the structure are correct when I view the resulting file in HDFView but the string is garbage. Any suggestions?

using System;
using HDF5DotNet;
using System.Runtime.InteropServices;
using System.IO;

namespace TestCompound
{
    class Program
    {
        const int N_RECORDS = 5; // number of records in the table
        const int N_FIELDS = 4; // number of fields
        const int RANK = 1;
        const string TABLE_NAME = "Test";
        const string FILE_NAME = "test_file2.h5";

        [StructLayout(LayoutKind.Explicit)]
        public struct testStruct2
        {
            [FieldOffset(0)]
            public int int1;
            [FieldOffset(4)]
            public byte[] char1; // assuming 9 characters + null termination
            [FieldOffset(14)]
            public double double1;
            [FieldOffset(22)]
            public double double2;
        }
        
        static void Main(string[] args)
        {
            try
            {

                // initialize the data
                testStruct2[] tsa = new testStruct2[N_RECORDS];
                for (int i = 0; i< N_RECORDS; i++)
                {
                    tsa[i].int1 = i;
                    byte[] barr1 = System.Text.Encoding.ASCII.GetBytes("testline" + i.ToString());
                    byte[] barr2 = new byte[10];
                    System.Buffer.BlockCopy(barr1, 0, barr2, 0, 9);
                    barr2[9] = 0; // null termination
                    tsa[i].char1 = barr2;
                    tsa[i].double1 = i * (i + 0.25);
                    tsa[i].double2 = 1 / (i + 1.25);
                }

                // create the file
                H5FileId fileId = H5F.create(FILE_NAME, H5F.CreateMode.ACC_TRUNC);

                // create the data space
                long[] dims = new long[1] { N_RECORDS };
                H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);

                // create the memory data type
                int structSize = Marshal.SizeOf(typeof(testStruct2));
                H5DataTypeId typeId = H5T.create(H5T.CreateClass.COMPOUND, structSize);

                // insert members
                string[] field_names = { "a", "b", "c", "d" };
                H5T.insert(typeId, field_names[0], Marshal.OffsetOf(typeof(testStruct2), "int1").ToInt32(), H5T.H5Type.NATIVE_INT);
                H5DataTypeId stDtId = H5T.copy(H5T.H5Type.C_S1);
                H5T.setSize(stDtId, 10);
                H5T.insert(typeId, field_names[1], Marshal.OffsetOf(typeof(testStruct2), "char1").ToInt32(), stDtId);
                H5T.insert(typeId, field_names[2], Marshal.OffsetOf(typeof(testStruct2), "double1").ToInt32(), H5T.H5Type.NATIVE_DOUBLE);
                H5T.insert(typeId, field_names[3], Marshal.OffsetOf(typeof(testStruct2), "double2").ToInt32(), H5T.H5Type.NATIVE_DOUBLE);

                 // create the dataset
                H5DataSetId dsetId = H5D.create(fileId, TABLE_NAME, typeId, spaceId);

                // Write the dataset.
                H5D.write<testStruct2>(dsetId, typeId, spaceId, spaceId, new H5PropertyListId(H5P.Template.DEFAULT), new H5Array<testStruct2>(tsa));
                // Close resources.
                H5D.close(dsetId);
                H5S.close(spaceId);
                H5T.close(typeId);
                H5F.close(fileId);
            }
            catch (HDFException anyHDF5E)
            {
                Console.WriteLine(anyHDF5E.Message);
            }
            catch (System.Exception sysE)
            {
                Console.WriteLine(sysE.TargetSite);
                Console.WriteLine(sysE.Message);
            }
        }
    }
}

Lonnie

Lonnie, how are you? I'm sure you are aware of the difference between
fixed-length and variable-length strings, and how the (C-) library deals with them.
Attached is an IronPython example similar to yours, but with a variable-length string
member. I believe your example is intended to use a fixed-length (10) member.
The problem might be your assignment

tsa[i].char1 = barr2;

which doesn't really initialize the 10 bytes you set aside for the string in tsa[i].

G.

h5_cmpd.py (5.4 KB)

···

From: Hdf-forum [mailto:hdf-forum-bounces@lists.hdfgroup.org] On Behalf Of Lonnie Hamm
Sent: Monday, June 8, 2015 6:38 AM
To: hdf-forum@lists.hdfgroup.org
Subject: [Hdf-forum] HDF5DotNet and string in compound data type

I know this question (or related to) has been asked a few times but the answers don't seem to be of any help to me. Below is my code. I am simply trying to write out a compound data type with one element being a string. All the numbers, i.e. int1, double1, and double2 in the structure are correct when I view the resulting file in HDFView but the string is garbage. Any suggestions?

using System;
using HDF5DotNet;
using System.Runtime.InteropServices;
using System.IO;

namespace TestCompound
{
    class Program
    {
        const int N_RECORDS = 5; // number of records in the table
        const int N_FIELDS = 4; // number of fields
        const int RANK = 1;
        const string TABLE_NAME = "Test";
        const string FILE_NAME = "test_file2.h5";

        [StructLayout(LayoutKind.Explicit)]
        public struct testStruct2
        {
            [FieldOffset(0)]
            public int int1;
            [FieldOffset(4)]
            public byte[] char1; // assuming 9 characters + null termination
            [FieldOffset(14)]
            public double double1;
            [FieldOffset(22)]
            public double double2;
        }

        static void Main(string[] args)
        {
            try
            {

                // initialize the data
                testStruct2[] tsa = new testStruct2[N_RECORDS];
                for (int i = 0; i< N_RECORDS; i++)
                {
                    tsa[i].int1 = i;
                    byte[] barr1 = System.Text.Encoding.ASCII.GetBytes("testline" + i.ToString());
                    byte[] barr2 = new byte[10];
                    System.Buffer.BlockCopy(barr1, 0, barr2, 0, 9);
                    barr2[9] = 0; // null termination
                    tsa[i].char1 = barr2;
                    tsa[i].double1 = i * (i + 0.25);
                    tsa[i].double2 = 1 / (i + 1.25);
                }

                // create the file
                H5FileId fileId = H5F.create(FILE_NAME, H5F.CreateMode.ACC_TRUNC);

                // create the data space
                long[] dims = new long[1] { N_RECORDS };
                H5DataSpaceId spaceId = H5S.create_simple(RANK, dims);

                // create the memory data type
                int structSize = Marshal.SizeOf(typeof(testStruct2));
                H5DataTypeId typeId = H5T.create(H5T.CreateClass.COMPOUND, structSize);

                // insert members
                string[] field_names = { "a", "b", "c", "d" };
                H5T.insert(typeId, field_names[0], Marshal.OffsetOf(typeof(testStruct2), "int1").ToInt32(), H5T.H5Type.NATIVE_INT);
                H5DataTypeId stDtId = H5T.copy(H5T.H5Type.C_S1);
                H5T.setSize(stDtId, 10);
                H5T.insert(typeId, field_names[1], Marshal.OffsetOf(typeof(testStruct2), "char1").ToInt32(), stDtId);
                H5T.insert(typeId, field_names[2], Marshal.OffsetOf(typeof(testStruct2), "double1").ToInt32(), H5T.H5Type.NATIVE_DOUBLE);
                H5T.insert(typeId, field_names[3], Marshal.OffsetOf(typeof(testStruct2), "double2").ToInt32(), H5T.H5Type.NATIVE_DOUBLE);

                 // create the dataset
                H5DataSetId dsetId = H5D.create(fileId, TABLE_NAME, typeId, spaceId);

                // Write the dataset.
                H5D.write<testStruct2>(dsetId, typeId, spaceId, spaceId, new H5PropertyListId(H5P.Template.DEFAULT), new H5Array<testStruct2>(tsa));
                // Close resources.
                H5D.close(dsetId);
                H5S.close(spaceId);
                H5T.close(typeId);
                H5F.close(fileId);
            }
            catch (HDFException anyHDF5E)
            {
                Console.WriteLine(anyHDF5E.Message);
            }
            catch (System.Exception sysE)
            {
                Console.WriteLine(sysE.TargetSite);
                Console.WriteLine(sysE.Message);
            }
        }
    }
}

Lonnie