Чтение структур C с типами "union" из C # с помощью PInvoke - PullRequest
7 голосов
/ 05 марта 2010

Я пытаюсь вывести на управляемую сторону (C #) структуру, построенную на C.

Предположим, эта структура (код C):

typedef struct S{
    int i;
    union{
        TypeA a;
        TypeB b;
        TypeC c;
    }uni;
 } S;  

Теперь я создаю классы-оболочки C #:

[StructLayout(LayoutKind.Explicit)]
public class S
{
    [FieldOffset(0)] 
    public int i;
    [FieldOffset(4)] 
    public TypeA a;
    [FieldOffset(4)]
    public TypeB b;
    [FieldOffset(4)]
    public TypeC c;
}

И у меня есть метод PInvoke для получения объекта S:
(Реализация C создает и возвращает структуру S с TypeA в объединенном поле)

[DllImport("Library.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.S)]
public static extern S getUnionStruct();

Где-то в основной функции я делаю:

S s = getUnionStruct();
Console.WriteLine("unions type: {0}",(S.a).GetType());

Результат - "AssembleName.TypeC" (???)

.net Framework принимает TypeC, потому что это был последний объявленный. Я также заметил, что если размер TypeC меньше, чем TypeA, я не могу прочитать все поля TypeA ..

Это ошибка в .net или я должен делать что-то другое?

1 Ответ

7 голосов
/ 05 марта 2010

Проблема заключается в использовании ссылочных типов для переноса неуправляемых типов. Когда CLR выполняет метод «GetType», он использует виртуальную таблицу, которая может содержать только один тип, который был последовательно переопределен в объявлении. Последнее объявленное поле выигрывает (в данном случае TypeC)
Переключение «класса» на «структуру» решает проблему.

[StructLayout(LayoutKind.Explicit)]
public struct S
{
    [FieldOffset(0)] 
    public int i;
    [FieldOffset(4)] 
    public TypeA a;
    [FieldOffset(4)]
    public TypeB b;
    [FieldOffset(4)]
    public TypeC c;
}

[StructLayout(LayoutKind.Sequencial)]
public struct TypeA
{
    //...
}

[StructLayout(LayoutKind.Sequencial)]
public struct TypeB
{
    //...
}

[StructLayout(LayoutKind.Sequencial)]
public struct TypeC
{
    //...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...