Как мне преобразовать структуру c dll в C # - PullRequest
1 голос
/ 03 января 2011

Я конвертирую приложение из c ++ в C # и у меня возник вопрос о правильном способе обработки импортируемых структур. Я пытаюсь преобразовать структуру из c dll в c # Структура в c выглядит так

typedef struct card_info
{
  ushort r;
  ushort s;
  enum_a a;
  usinged long ul;
  ushort n;
  ushort* b;
  ushort id;
} CARD_INFO;

когда я использую [StructLayout (LayoutKind.Sequentaial)], размер массива составляет 20 байт в c #. Однако, если взглянуть на мой рабочий код на c ++, то это 24 байта. Я изменил свой C #, чтобы выглядеть так:

[StructLayout(LayoutKind.Explicit)]
public struct CardInfo
{
  [FieldOffset(0) public ushort r;
  [FieldOffset(2) public ushort s;
  [FieldOffset(4) public EnumA a;
  [FieldOffset(8) public ushort ul;
  [FieldOffset(12) public ushort n;
  [FieldOffset(16) public UInt32 b;
  [FieldOffset(20) public ushort id;
}

Это похоже на компиляцию, но я не уверен, что это правильный способ сделать это. Пожалуйста, дайте мне знать, если это правильно или есть лучший способ.

Спасибо

Ответы [ 3 ]

4 голосов
/ 03 января 2011
usinged long ul;

Это опечатка, но это определенно не короткий, а уинт.

Также не используйте FieldOffset, дайте компилятору понять это. Теперь Marshal.SizeOf () вернет 24, вставлено правильное количество отступов. Член b должен иметь значение IntPtr.

1 голос
/ 03 января 2011

@ Ответ Ханса верен, но я просто добавлю несколько советов по отладке данных на маршале, чтобы вы могли видеть результаты.Я просто создаю экземпляр структуры и создаю указатель на нее следующим образом.

CardInfo cardInfo = new CardInfo();
IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(cardInfo));
Marshal.StructureToPtr(cardInfo, pointer, false);

Вставьте точку останова в последнюю строку этого и войдите в отладчик, пока он не сломается.Вы должны увидеть pointer в окнах locals / autos, и его значением должно быть некоторое значение типа int.(Здесь лучше всего работает шестнадцатеричный дисплей).

Img1

Перейдите в окно команд и введите dc 0x0086bf30 <- адрес вашего указателя.Он должен выгружать данные из памяти.Повторный ввод <code>dc сбросит следующие фрагменты памяти.Вы также можете использовать da, db, dd, df, dq для вывода данных в виде различных типов.Попробуйте перешагнуть через точку останова далее (F10) и снова сбросить ту же память.

Img2

Вы можете инициализировать поля вашей структуры с определенными значениями и наблюдать изменения здесь, чтобы увидетьесли работает как надо.

0 голосов
/ 03 января 2011

ul - это длинная без знака в реализации C, но вы используете короткую без знака. Это было бы хорошим началом, если вам интересно, почему ваша реализация StructLayout.Sequential слишком мала.

Я также дважды проверил бы вашу реализацию EnumA, чтобы убедиться, что это правильный размер.

...