Pergunta

Eu tenho uma struct não gerenciado Eu gostaria de organizar a c afiada que parece basicamente assim:

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

Eu acredito que eu tenho que escrever uma marshaller costume, mas não tenho certeza sobre como proceder.

Foi útil?

Solução

Eu gosto de usar uma configuração como esta quando eu não precisam diretamente crianças índice:

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;
            }
        }
    }
}

Se você do necessidade da própria criança índice, a coisa mais fácil é criar um GetChild método (mostrado abaixo). A maneira mais difícil é criar uma classe auxiliar / wrapper que implementa IList<MyStruct>. Um exemplo seria devolvido a partir da propriedade Children, e sua interno funcionaria chamando o método GetChild. Isso é deixado como um exercício para o leitor deve ele precisa.

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;
}

Outras dicas

Se você quiser apenas para passá-lo para alguma função não gerenciado, você pode simplesmente usar o código inseguro e stackalloc / corrigir um array para obter um ponteiro para a matriz de objetos.

        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);


        }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top