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