Как мне преобразовать рекурсивную структуру в c Sharp?

StackOverflow https://stackoverflow.com/questions/1150194

Вопрос

У меня есть неуправляемая структура, которую я хотел бы маршалировать в 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