Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I marshall a recursive struct to c sharp?

I have an unmanaged struct I'd like to marshal to c sharp that looks basically like this:

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

I believe that I have to write a custom marshaller but I'm not sure on how to proceed.

like image 304
Roald Avatar asked Oct 16 '25 17:10

Roald


1 Answers

I like to use a setup like this when I don't need to directly index children:

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

If you do need to directly index children, the easiest thing is creating a method GetChild (shown below). The harder way is creating a helper/wrapper class that implements IList<MyStruct>. An instance would be returned from the Children property, and its internal would work by calling the GetChild method. This is left as an exercise to the reader should he need it.

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;
}
like image 111
Sam Harwell Avatar answered Oct 18 '25 06:10

Sam Harwell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!