C # P / Invoke: Как добиться двойной косвенности для поля структурированного параметра - PullRequest
1 голос
/ 04 июня 2009

Я звоню в родной 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 Ответ

4 голосов
/ 04 июня 2009

Без пользовательского 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;
}
...