Как изменить индекс ссылки на массив с не использовать указатель в C #? - PullRequest
0 голосов
/ 01 июля 2019

Я пишу код для разбора пакетов.

Я хочу изменить ссылочный адрес массива, но я не знаю, как изменить ссылочный адрес без использования указателя. Если я скопирую часть массива, я думаю, что он замедлится. Если я использую указатель, это будет небезопасно.

Ниже приведен код, который я пишу.

public class Datagrams : LinkedList<DatagramPacket>
{
    public Datagrams(byte[] RowData) : base()
    {
        AddLast(new DatagramPacket(RowData));
        while(Last.Value.header.Length.LastIndicator)
        {
            ///////////////////////////////////////////
            //I want do that. But this is unsafe code//
            ///////////////////////////////////////////
            AddLast(new DatagramPacket( RowData + sizeof[Last.Value] ));
        }
    }
}

public class DatagramPacket : Packet
{
    public enum DatagramCmd : Byte
    {
        NOP = 0x0,
        APRD = 0x1,
        APWR = 0x2,
        APRW = 0x3,
        FPRD = 0x4,
        FPWR = 0x5,
        FPRW = 0x6,
        BRD = 0x7,
        BWR = 0x8,
        BRW = 0x9,
        LRD = 0xA,
        LWR = 0xB,
        LRW = 0xC,
        ARMW = 0xD,
        FRMW = 0xE
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct DatagramAddr
    {
        [MarshalAs(UnmanagedType.U4), FieldOffset(0)]
        public UInt32 LogicalAddr;
        [MarshalAs(UnmanagedType.U2), FieldOffset(0)]
        public UInt16 SlaveAddr;
        [MarshalAs(UnmanagedType.U2), FieldOffset(2)]
        public UInt16 OffsetAddr;
    }

    public struct DatagramLength
    {
        [MarshalAs(UnmanagedType.U2)]
        public UInt16 bits;

        public int Length { get => bits & 0x07FF; }
        public bool Valid { get => (bits & 0x0380) == 0; }
        public bool RoundTrip { get => (bits & 0x4000) != 0; }
        public bool LastIndicator { get => (bits & 0x8000) != 0; }
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct DatagramHeader
    {
        [MarshalAs(UnmanagedType.U1)]
        public DatagramCmd Cmd;
        [MarshalAs(UnmanagedType.U1)]
        public Byte Index;
        [MarshalAs(UnmanagedType.Struct)]
        public DatagramAddr Addr;
        [MarshalAs(UnmanagedType.Struct)]
        public DatagramLength Length;
        [MarshalAs(UnmanagedType.U2)]
        public UInt16 Interrupt;
    }

    public DatagramHeader header;
    public UInt16 wc;  //Working Count

    public DatagramPacket(byte[] RowData) : base(RowData)
    {
        header = new DatagramHeader();
        GCHandle handle = GCHandle.Alloc(RowData, GCHandleType.Pinned);
        try
        {
            header = (DatagramHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(DatagramHeader));
        }
        finally
        {
            handle.Free();
        }
        body = new byte[header.Length.Length];
        Buffer.BlockCopy(RowData, Marshal.SizeOf<DatagramHeader>(), body, 0, body.Length);
        wc = BitConverter.ToUInt16(RowData, Marshal.SizeOf<DatagramHeader>() + body.Length);
    }

    public override Packet Parse()
    {
        throw new NotImplementedException();
    }
}

Есть ли способ изменить ссылку без использования указателя?

1 Ответ

0 голосов
/ 01 июля 2019

Я уже решил проблему, скопировав массив, как показано ниже, но я думаю, что это будет медленнее, чем ссылаться на него любым способом.Я пытался обрабатывать пакеты в реальном времени для отображения графика, но должен ли я отказаться от обработки в реальном времени так же, как использую .net?

 public class Datagrams : LinkedList<DatagramPacket>
{
    public Datagrams(byte[] RowData) : base()
    {
        AddLast(new DatagramPacket(RowData));
        while(Last.Value.header.Length.LastIndicator)
        {
            int index = Marshal.SizeOf<DatagramPacket.DatagramHeader>() + Last.Value.header.Length.Length + sizeof(UInt16);
            byte[] temp = new byte[RowData.Length - index];
            Buffer.BlockCopy(RowData, index, temp, 0, RowData.Length - index);
            RowData = temp;
            AddLast(new DatagramPacket(RowData));
        }
    }
}
...