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;
}
Другие вопросы по тегам