سؤال

رمز 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 ++.

بدلا من ذلك ، باستخدام هذا الملف المصدر يمكن القيام بالمهمة بالنسبة لنا ، ولكن ليس إذا كان هناك صفيف في الهيكل.

هل كانت مفيدة؟

المحلول

أعتقد أن ما تبحث عنه (إذا كنت تستخدم تعريف هيكل مماثل مثل 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

نصائح أخرى

لست متأكدًا مما تطلبه بالضبط. هل تحاول الحصول على تعريف هيكل مكافئ في C# للاستخدام القديم C# أو لأغراض interop (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# ولا يمكنك إجبار الصفيف على أن يكون حجمًا محددًا من خلال التهيئة.

هناك خياران بديلان في العالم المدارة.

استخدم بنية تحتوي على طريقة إنشاء تملأ الصفيف

[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 مباشرة.

تعديل OP Watns لمعرفة كيفية تحويل بايت [] إلى قيمة tpacket

لسوء الحظ ، لا توجد طريقة رائعة للقيام بذلك في C#. كان C ++ رائعًا لهذا النوع من المهمة لأن لديه نظام نوع ضعيف للغاية حيث يمكنك اختيار عرض تيار من البايت كهيكل معين (صب مؤشر شرير).

قد يكون هذا ممكنًا في رمز C# غير الآمن ، لكنني لا أعتقد أنه كذلك.

في الأساس ما يجب عليك فعله هو تحليل البايتات يدويًا وتعيينها للقيم المختلفة في البنية. أو اكتب طريقة أصلية تقوم بإلقاء نمط C و Pinvoke في هذه الوظيفة.

يمكن أن يتم ذلك باستخدام رمز غير آمن أيضًا ، على الرغم من أنه يقيد السياق الذي يمكن للموجود بموجبه تشغيل البرنامج ، وبطبيعة الحال ، يقدم إمكانية وجود عيوب أمان. الميزة هي أنك تم إلقاؤك مباشرة من صفيف إلى الهيكل باستخدام المؤشرات ، كما أنها خالية من الصيانة إذا كنت ستضيف أو تزيل الحقول فقط من البنية. ومع ذلك ، فإن الوصول إلى المصفوفات يتطلب استخدام النظام الثابت حيث لا يزال بإمكان 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
}

بالنسبة لهذا النوع من التعليمات البرمجية ، من المهم للغاية التحقق من أن طول الصفيف يطابق تمامًا حجم الهيكل ، وإلا فسوف تفتح لبعض التدفقات العازلة السيئة. كما غير آمن تم تطبيق الكلمة الرئيسية على البنية بأكملها ، فأنت لا تحتاج إلى وضع علامة على كل طريقة أو كودبلوك على أنها منفصلة غير آمن صياغات.

يمكنك وضع ما يتطلع إلى العالم الخارجي مثل مجموعة من الحجم الثابت داخل بنية آمنة عن طريق كتابة وظائف داخل الهيكل للوصول. على سبيل المثال ، إليك مجموعة ثابتة 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 مع الإسناد
لا تنتمي إلى StackOverflow
scroll top