计算嵌套C#结构的C结构等价物的大小-如何访问嵌套结构?

2ledvvac  于 2023-06-05  发布在  C#
关注(0)|答案(1)|浏览(311)

我怎样才能获得嵌套到另一个结构中的结构的引用,以递归地调用一个函数并处理整个结构?
我正在编写一个C#函数来计算C#结构体的大小,如果用C编写相同的结构体。因此,代码的目标是计算接收到的C#结构的C结构的大小。所接收的C#结构可以具有其他嵌套结构以及位域变量。C#不实现位域,所以我不得不使用属性以某种方式实现位域(我不能直接使用Marshal.SizeOf(my_struct)):

[StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct struct_b{// typedef struct __attribute__((packed)){    
        [BitfieldLength(1)]
        public byte flag_a;// uint8_t flag_a  :1;
        [BitfieldLength(1)]
        public byte flag_b;// uint8_t flag_b  :1;
        [BitfieldLength(2)]
        public byte flag_c;// uint8_t flag_c  :2;
        [BitfieldLength(1)]
        public byte flag_d;// uint8_t flag_d  :1;
        [BitfieldLength(3)]
        public byte reserved;// uint8_t reserved  :3;
        public float measure_1;//float measure_1
        public float measure_2;//float measure_2
        public UInt32 value_1; // uint32_t value_1;
    }// struct_b;

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct struct_a{ 
        // typedef struct __attribute__((packed)){
        public Int16 i_value_a;// int16_t i_value_a;
        public struct_b struct_field_b; //struct_b struct_field_b;
    }// struct_a

这是我想递归调用的函数,我需要从它访问嵌套结构。它在没有其他嵌套结构的情况下工作,但我不想添加计算包含其他嵌套结构的结构的大小的功能,但我不知道如何获得具有嵌套结构的信息和父结构的字段的对象:

public static int SizeInPackedBytes(object structure, int i_start_idx, ref string str_parsed_struct){
            int i_bitset_counter = 0;
            int i_num_bits = 0;
            int i_byte_index = 0;
            int i_aux = 0;
            bool b_is_struct = false;
            int i_field_idx = 0;

            // get and then process all the fileds of the received object with the structure
            i_bitset_counter = 0;
            i_byte_index = 0;
            i_field_idx = 0;
            FieldInfo[] field_info_array = structure.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            for (i_field_idx = 0; i_field_idx < field_info_array.Count(); i_field_idx++){

                FieldInfo field_info = field_info_array[i_field_idx];

                // check if the currently processed field of the received struct corresponds to another nested struct: structs are ValueType not Primitive and not Enums ....
                b_is_struct = (field_info.FieldType.IsValueType && !field_info.FieldType.IsPrimitive && !field_info.FieldType.IsEnum);// structs are Value Types but not Primitive Types and not Primitive Types
                if (b_is_struct){

// >>> HERE: i don't know how to get the reference to the nested struct to recursivelly call again SizeInBytesPacked(object structure)
// something like:
// >>            object nested_struct = f_info_array[i_field_idx]                    
// >>            i_byte_index = i_byte_index + SizeInBytesPacked(nested_struct);

                }else{

                    // the current processed field does not corresponds to a nested struct, so check its attributes to detect if it corresponds to a bitfield or to a standard value type field

                    object[] attrs = field_info.GetCustomAttributes(typeof(BitfieldLengthAttribute), false);
                    if (attrs.Length == 1){

                        // the current field corresponds to a bitset!

                        // get the number of bits of the current processed field defined in the corresponding [BitfieldLength(x)]
                        i_num_bits = ((BitfieldLengthAttribute)attrs[0]).Length;

                        str_parsed_struct = str_parsed_struct + "[" + (i_start_idx + i_byte_index).ToString("D3") + "] Size: " + i_num_bits.ToString("D3") + " bits \"" + field_info.Name + "\" bit " + i_bitset_counter + " to " + ((i_bitset_counter + i_num_bits) % 8) + "\r\n";

                        i_bitset_counter = i_bitset_counter + i_num_bits;

                        // if the i_bitset_counter is beyond the current byte index then place the byte index
                        // at the end of the current field according to the size of the field
                        if (i_bitset_counter >= 8)
                        {
                            // started a new bitset 
                            i_byte_index = i_byte_index + (int)(i_bitset_counter / 8);
                            i_bitset_counter = i_bitset_counter % 8;
                        }//if

                    }else{

                        // current field type is not a bitset

                        // if the previous field was a bitset which did not have the 'reserved' bits 
                        // properly set, then try to byte-realign the following field
                        if (i_bitset_counter != 0){
                            i_byte_index++;
                        }
                        i_bitset_counter = 0;// reset the var used to count the bits in the bitsets

                        var struct_field_value = field_info.GetValue(structure);
                        Type test = struct_field_value.GetType();
                        i_aux = Marshal.SizeOf(test);

                        str_parsed_struct = str_parsed_struct + "[" + (i_start_idx + i_byte_index).ToString("D3") + "] Size: " + i_aux.ToString("D3") + " bytes \"" + field_info.Name + "\" \r\n";

                        i_byte_index = i_byte_index + i_aux;

                    }//if

                }//if

            }//for

            ...

}//SizeInPackedBytes

我想在接收到的结构中获取嵌套结构的引用,将它们存储在一个对象中,并递归调用前面的函数来处理它们。换句话说,我如何从FieldInfo变量中获取一个结构体,我知道它引用了一个结构体,类似于这样:

FieldInfo field_local = f_info_array[i_field_idx];
   object nested_struct = field_local.GetValue(null);
csbfibhn

csbfibhn1#

最后,它比我想象的要容易,我只需要将前面函数中标记为“HERE >>”的块替换为:

...
// check if the currently processed field of the received struct corresponds to another nested struct: structs are ValueType not Primitive and not Enums ....
b_is_struct = (field_info.FieldType.IsValueType && !field_info.FieldType.IsPrimitive && !field_info.FieldType.IsEnum);// structs are Value Types but not Primitive Types and not Primitive Types
if (b_is_struct){

    // current processed field is a nested struct, so process it recursivelly to get its size                    

    // get the reference to the nested structure and calculate its size by recursivelly calling the current function
    object nested_structure = field_info.GetValue(structure);
    str_parsed_struct = str_parsed_struct + field_info_array[i_field_idx].Name + "{\r\n";
    i_byte_index = i_byte_index + PrimitiveConversion.SizeInPackedBytes(nested_structure, i_byte_index, ref str_parsed_struct);
    str_parsed_struct = str_parsed_struct + "}//"+ field_info_array[i_field_idx].Name +"\r\n";

}else{
...

这允许我获得嵌套结构,然后递归地将其传递给函数。

相关问题