簡體   English   中英

如何在C#中的結構中放置一個數組?

[英]How can I put an array inside a struct in C#?

C ++代碼:

struct tPacket
{
    WORD word1;
    WORD word2;
    BYTE byte1;
    BYTE byte2;
    BYTE array123[8];
}

static char data[8192] = {0};
...
some code to fill up the array
...
tPacket * packet = (tPacket *)data;

我們不能在C#中輕松做到這一點。

請注意,C ++結構中有一個數組。

或者,使用此源文件可以為我們完成工作,但如果結構中有數組則不行。

我不確定你究竟在問什么。 您是否嘗試在C#中獲取等效的結構定義以用於普通的舊C#用法或用於互操作(PInvoke)目的? 如果它適用於PInvoke,則follownig結構將起作用

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tPacket {

    /// WORD->unsigned short
    public ushort word1;

    /// WORD->unsigned short
    public ushort word2;

    /// BYTE->unsigned char
    public byte byte1;

    /// BYTE->unsigned char
    public byte byte2;

    /// BYTE[8]
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=8, ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]
    public byte[] array123;
}

如果您正在尋找具有相同特征的普通舊C#結構,那么遺憾的是不可能使用結構。 您無法在C#結構中定義常量大小的內聯數組,也無法通過初始化程序強制數組為特定大小。

托管世界中有兩種備選方案。

使用具有填充數組的create方法的結構

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tPacket {
    public ushort word1;
    public ushort word2;
    public byte byte1;
    public byte byte2;
    public byte[] array123;
    public static tPacket Create() { 
      return new tPacket() { array123 = new byte[8] };
    }
}

或者使用一個類,您可以直接初始化array123成員變量。

EDIT OP知道如何將byte []轉換為tPacket值

不幸的是,在C#中沒有很好的方法可以做到這一點。 C ++對於這種任務很棒,因為它有一個非常弱的類型系統,你可以選擇將字節流視為一個特定的結構(邪惡的指針轉換)。

這在C#不安全代碼中可能是可能的,但我不相信。

基本上,您需要做的是手動解析字節並將它們分配給結構中的各種值。 或者編寫一個本地方法,將C樣式轉換和PInvoke轉換為該函數。

我認為你正在尋找的(如果你使用像JaredPar發布的類似結構定義)是這樣的:

tPacket t = new tPacket();
byte[] buffer = new byte[Marshal.SizeOf(typeof(tPacket))];
socket.Receive(buffer, 0, buffer.length, 0);

GCHandle pin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
t = (tPacket)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(tPacket));
pin.free();

//do stuff with your new tPacket t

它也可以用不安全的代碼來完成,雖然它限制了程序可以運行的上下文,並且自然會引入安全漏洞的可能性。 優點是您使用指針直接從數組轉換到結構,如果您只想在結構中添加或刪除字段,它也是免維護的。 但是,訪問數組需要使用fixed語句,因為當GC包含在對象中時,GC仍然可以在內存中移動結構。

這是我用於解釋UDP數據包的不安全結構的一些修改代碼:

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public unsafe struct UnsafePacket
{
    int time;
    short id0;
    fixed float acc[3];
    short id1;
    fixed float mat[9];

    public UnsafePacket(byte[] rawData)
    {
        if (rawData == null)
            throw new ArgumentNullException("rawData");
        if (sizeof(byte) * rawData.Length != sizeof(UnsafePacket))
            throw new ArgumentException("rawData");

        fixed (byte* ptr = &rawData[0])
        {
            this = *(UnsafePacket*)rawPtr;
        }
    }

    public float GetAcc(int index)
    {
        if (index < 0 || index >= 3)
            throw new ArgumentOutOfRangeException("index");
        fixed (UnsafePacket* ptr = &acc)
        {
            return ptr[index];
        }
    }

    public float GetMat(int index)
    {
        if (index < 0 || index >= 9)
            throw new ArgumentOutOfRangeException("index");
        fixed (UnsafePacket* ptr = &mat)
        {
            return ptr[index];
        }
    }

            // etc. for other properties
}

對於這種代碼,檢查數組的長度是否與struct的大小完全匹配是非常重要的,否則你將打開一些討厭的緩沖區溢出。 由於unsafe關鍵字已應用於整個結構,因此您無需將每個方法或代碼塊標記為單獨的不安全語句。

通過在結構中編寫函數進行訪問,您可以將外觀世界看起來像安全結構中的固定大小數組。 例如,這是一個安全結構中固定的4乘4雙精度數組:

public struct matrix4 //  4 by 4 matrix  
{  
    //  
    //  Here we will create a square matrix that can be written to and read from similar  
    //  (but not identical to) using an array.  Reading and writing into this structure  
    //  is slower than using an array (due to nested switch blocks, where nest depth  
    //  is the dimensionality of the array, or 2 in this case).  A big advantage of this  
    //  structure is that it operates within a safe context.  
    //  
    private double a00; private double a01; private double a02; private double a03;  
    private double a10; private double a11; private double a12; private double a13;  
    private double a20; private double a21; private double a22; private double a23;  
    private double a30; private double a31; private double a32; private double a33;  
    //
    public void AssignAllZeros()                    //  Zero out the square matrix  
    { /* code */}               
    public double Determinant()                     //  Common linear algebra function  
    { /* code */}  
    public double Maximum()                         //  Returns maximum value in matrix  
    { /* code */}  
    public double Minimum()                         //  Minimum value in matrix  
    { /* code */}  
    public double Read(short row, short col)        //  Outside read access   
    { /* code */}  
    public double Read(int row, int col)            //  Outside read access overload  
    { /* code */}  
    public double Sum()                             //  Sum of 16 double precision values  
    {  
        return a00 + a01 + a02 + a03 + a10 + a11 + a12 + a13 + a20 + a21 + a22 + a23 + a30 + a31 + a32 + a33;  
    }  
    public void Write(short row, short col, double doubleValue)  //  Write access to matrix  
    { /* code */}  
    public void Write(int row, int col, double doubleValue)      //  Write access overload  
    { /* code */}              
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM