views:

346

answers:

2

I am calling into a native dll from C#. For the specific function in question, one of the parameters I need is a structure which contains a doubly-indirect field (pointer to a pointer).

For example, take the following C prototype and structs:

int someFunc(SomeStruct* result);

struct SomeStruct
{
     DWORD foo;
     AnotherStruct** ppResultStruct;
}

struct AnotherStruct
{
     DWORD bar;
}

The following C# code provides only a single level of indirection for the field AnotherStruct, which is incorrect:

[DllImport("my.dll")]
public static extern int someFunc(SomeClass result);

[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
    int foo;
    AnotherClass resultClass;
}

[StructLayout(LayoutKind.Sequential)]
public class AnotherClass
{
    int bar;
}

How can I achieve the double-indirection that's required here? I know how to do it in the case of a doubly-indirect parameter to a function, but I'm confused by the fact that it's embedded in a struct.

Maybe I should declare the AnotherClass field as an IntPtr, and then resort to unsafe code to assign it an appropriate value. Is that a valid approach, and are there any other/better options?

+4  A: 

Without a custom marashaler you cannot build a class that both contains a standard inline struct definition and double indirection. This type of marshaling requires a bit of magic to achieve.

The best way to approach this is to treat the double indirection as a pointer which it actual is. Then use a pretty property to take care of the evilness

[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
    int foo;
    IntPtr resultPtr;
    AnotherStruct resultStruct { 
      get { 
        var temp = (IntPtr)Marshal.PtrToStructure(resultPtr, typeof(IntPtr));
        return (AnotherStruct)Marshal.PtrToStructure(temp, typeof(AnotherStruct));
      }
    }

}

[StructLayout(LayoutKind.Sequential)]
public class AnotherStruct
{
    int bar;
}
JaredPar
+1 Manual marshaling is the only way to go with double indirection. Though you would probably want to use: var temp = Marshal.ReadIntPtr(resultPtr); rather than PtrToStructure.
Stephen Martin
A: 

How do you doubly indirect a parameter to a function??

ronak
If you have a question, you should post it using the "ask question" button at the top right. Also, you'll need to provide more details in order to get any useful responses.
Odrade