C# P/Invoke: Как добиться двойной косвенности для поля структурированного параметра
Я звоню в родной DLL из C#. Для конкретной рассматриваемой функции один из необходимых мне параметров - это структура, которая содержит дважды косвенное поле (указатель на указатель).
Например, возьмем следующий прототип C и структуры:
int someFunc(SomeStruct* result);
struct SomeStruct
{
DWORD foo;
AnotherStruct** ppResultStruct;
}
struct AnotherStruct
{
DWORD bar;
}
Следующий код C# обеспечивает только один уровень косвенности для поля AnotherStruct, что неверно:
[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;
}
Как я могу добиться двойного косвенного обращения, которое требуется здесь? Я знаю, как это сделать в случае двояко-косвенного параметра для функции, но меня смущает тот факт, что он встроен в структуру.
Может быть, мне следует объявить поле AnotherClass как IntPtr, а затем прибегнуть к небезопасному коду, чтобы присвоить ему подходящее значение. Это правильный подход, и есть ли другие / лучшие варианты?
1 ответ
Без пользовательского marashaler вы не можете создать класс, который содержит стандартное определение встроенной структуры и двойное косвенное обращение. Этот тип маршалинга требует немного магии для достижения.
Лучший способ приблизиться к этому состоит в том, чтобы рассматривать двойную косвенность как указатель, которым она является на самом деле. Тогда используйте красивое свойство, чтобы позаботиться о зле
[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;
}