![](/img/trans.png)
[英]C# How can I declare a Dictionary inside a struct that is being marshalled to get the sizeof the struct?
[英]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.