سؤال

لدي بنية غير مدارة، أود أن مارشال ل C Sharp التي تبدو أساسا مثل هذا:

struct MyStruct{  
    /* ... some stuff ... */
    int numChilds;  
    MyStruct *childs;
}

أعتقد أنه لا بد لي من كتابة مارشالر مخصص لكنني لست متأكدا من كيفية المتابعة.

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

المحلول

أحب استخدام برنامج الإعداد مثل هذا عندما لا أحتاج إلى الفهرس مباشرة للأطفال:

struct MyStruct
{
    /* ... some stuff ... */
    int numChilds;
    IntPtr childData;

    public IEnumerable<MyStruct> Children
    {
        get
        {
            int elementSize = Marshal.SizeOf(typeof(MyStruct));
            for (int i = 0; i < this.numChilds; i++)
            {
                IntPtr data = new IntPtr(this.childData.ToInt64() + elementSize * i);
                MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
                yield return child;
            }
        }
    }
}

اذا أنت فعل تحتاج إلى فهرس الأطفال مباشرة، أسهل شيء هو إنشاء طريقة GetChild (ظاهر أدناه). الطريقة الصعبة هي إنشاء فئة المساعد / المجمع التي تنفذ IList<MyStruct>. وبعد سيتم إرجاع مثيل من Children الممتلكات، وسوف تعمل الداخلية عن طريق الاتصال GetChild طريقة. يترك هذا بمثابة تمرين للقارئ إذا كان يحتاج إليه.

public MyStruct GetChild(int index)
{
    if (index < 0)
        throw new ArgumentOutOfRangeException("index", "The index must be >= 0.");
    if (index >= this.numChilds)
        throw new ArgumentException("The index must be less than the number of children", "index");

    int elementSize = Marshal.SizeOf(typeof(MyStruct));
    IntPtr data = new IntPtr(childData.ToInt64() + elementSize * index);
    MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct));
    return child;
}

نصائح أخرى

إذا كنت تريد فقط تمريرها إلى بعض الوظائف غير المدارة، فيمكنك فقط استخدام الرمز غير الآمن و Stackalloc / إصلاح صفيف للحصول على مؤشر إلى صفيف الكائنات.

        unsafe struct Foo
        {
            public int value;
            public int fooCount;
            public Foo* foos;
        }

        [DllImport("dll_natv.dll")]
        static extern void PrintFoos(Foo f);

        public unsafe static void Main()
        {
            Foo* foos = stackalloc Foo[10];

            for (int i = 0; i < 10; ++i)
                foos[i].value = i;

            Foo mainFoo = new Foo();
            mainFoo.fooCount = 10;
            mainFoo.value = 100;
            mainFoo.foos = foos;

            PrintFoos(mainFoo);


        }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top