Как объявить объединение в C #? - PullRequest
3 голосов
/ 26 ноября 2009

Соблюдайте следующий пример кода:

struct DDD
{
  [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 512, ArraySubType = UnmanagedType.I1)]
  byte[] x;
}

struct BBB
{
  DDD x;
}

struct CCC
{
  DDD x;
  ulong y;
  ulong z;
}

[StructLayout(LayoutKind.Explicit)]
struct AAA
{
  [FieldOffsetAttribute(0)]
  BBB a;
  [FieldOffsetAttribute(0)]
  CCC b;
}

К сожалению, AAA не может быть загружен, попытка выполнить new AAA() завершается неудачно с System.TypeLoadException: Could not load type 'AAA' from assembly 'Shunra.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=807fc02bc4ce69db' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.

Как с этим справиться?

Спасибо.

EDIT:

Кстати, это урезанная версия структуры взаимодействия MINIDUMP_CALLBACK_INPUT, созданного PInvokeTool (исходная структура определена в DbgHelp.h)

Ответы [ 3 ]

2 голосов
/ 26 ноября 2009

Проблема в том, что независимо от того, что вы указываете для MarshalAsAttribute, массив является массивом является управляемым объектом. Чтобы ваш код работал, вам нужно избавиться от управляемого массива. Для этого у вас есть два варианта:

Вариант 1:

Преобразование массива в буфер фиксированного размера, что означает изменение определения DDD следующим образом:

unsafe struct DDD {
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 512, ArraySubType = UnmanagedType.I1)]
    fixed byte x[512];
}

(я не уверен, нужен ли атрибут MarshalAs, но я сомневаюсь в этом.)

Теперь вы используете небезопасную структуру, поэтому вам нужно скомпилировать с ключом / unsafe.

Вариант 2:

Преобразовать массив в 512 байтов членов. Самый простой способ - использовать 64 длинных:

struct DDD {
    long x1;
    long x2;
    long x3;
    ...
}

Редактировать: Уточнено.

0 голосов
/ 26 ноября 2009

Я думаю, что вам нужно добавить конструктор в Struct для создания экземпляров типов BBB и CCC, в свою очередь, в каждой из других структур BBB и CCC вам также понадобится конструктор для создания экземпляров типа DDD.

struct DDD
{
  [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 512, ArraySubType = UnmanagedType.I1)]
  byte[] x;
}

struct BBB
{
  DDD x;
  public BBB(){
     x = new DDD();
  }
}

struct CCC
{
  DDD x;
  ulong y;
  ulong z;
  public CCC(){
     x = new DDD();
  }
}

[StructLayout(LayoutKind.Explicit)]
struct AAA
{
  [FieldOffsetAttribute(0)]
  BBB a;
  [FieldOffsetAttribute(0)]
  CCC b;
  public AAA(){
     a = new BBB();
     b = new CCC();
  }
}

Единственный улов в этом вопросе - создание экземпляра struct DDD, которая неизвестна, поскольку вы объявили поле x, которое является массивом byte [], а размер неизвестен, поэтому вы должны обращаться с ним на основе ваших собственных требований. , Может быть, передать параметр, возможно, int, указывающий размер массива ...

Надеюсь, это поможет вам, С наилучшими пожеланиями, Том.

0 голосов
/ 26 ноября 2009

Мне кажется, что у вас не может быть двух FieldOffsetAttribute со смещением 0.

Убедитесь, что вы посмотрите на его определение в библиотеке MSDN: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.fieldoffsetattribute.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...