Выделение структуры из указателя в x64

1

У меня три структуры:

    [StructLayout(LayoutKind.Sequential)]
    internal struct COPYDATASTRUCT
    {
        public IntPtr dwData;       // Specifies data to be passed
        public int cbData;          // Specifies the data size in bytes
        public IntPtr lpData;       // Pointer to data to be passed
    }

    public struct SHELLTRAYDATA
    {
        public UInt32 dwUnknown;
        public UInt32 dwMessage;
        public NID_XX nid;
    }

    public struct NID_XX
    {
        public UInt32 cbSize;
        public IntPtr hWnd;
        public uint uID;
        public uint uFlags;
        public uint uCallbackMessage;
        public IntPtr hIcon;
    }

В моем WndProc я делаю следующее:

      case WM_COPYDATA:
                {
                    COPYDATASTRUCT cp = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
                    if(cp.dwData == SH_TRAY_DATA)
                    {
                        var shellTrayData = (SHELLTRAYDATA)Marshal.PtrToStructure(cp.lpData,typeof(SHELLTRAYDATA));
                        HandleNotification(shellTrayData);
                    }
                }

Когда мое приложение работает на x86, оно отлично работает. Когда я запускаю его на x64, я не получаю hIcon и, кроме того, hWnd недействителен. Когда я нацеливаю приложение на x86 и запускаю его на x64, он работает нормально. Я знаю, что проблема кроется в Маршаллинге. Нужно ли вручную маршалировать структуру? Нужна помощь по этому поводу. Я бы предпочел иметь одну и ту же структуру для x64 и x86

РЕДАКТИРОВАТЬ:

Неуправляемые структуры:

typedef struct tagCOPYDATASTRUCT 
{
    ULONG_PTR dwData;
    DWORD cbData;
    _Field_size_bytes_(cbData) PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

// data sent by shell via Shell_NotifyIcon
typedef struct _SHELLTRAYDATA
{
    DWORD dwUnknown;
    DWORD dwMessage;
    NID_XX nid;
} *PSHELLTRAYDATA;

// sub structure common to all others


  typedef struct
  {
  DWORD cbSize;
  HWND hWnd;
  UINT uID;
  UINT uFlags;
  UINT uCallbackMessage;
  HICON hIcon;
  } NID_XX, *PNID_XX;
  typedef const NID_XX * PCNID_XX;

EDIT: Размеры структур следующие:

Неуправляемый:

  1. COPYDATASTRUCT: 12 (X86) и 24 (x64)
  2. SHELLTRAYDATA: 32 (X86) и 48 (X64)
  3. NID_XX: 24 (X86) и 40 (X64)

Удалось:

  1. COPYDATASTRUCT: 12 (X86) и 24 (x64)
  2. SHELLTRAYDATA: 32 (X86) и 48 (X64)
  3. NID_XX: 24 (X86) и 40 (X64)

То же самое и с обеих сторон.

  • 3
    Ответ на этот вопрос можно найти, изучив определения неуправляемой структуры. Вы не представили их. Это взаимодействие Взаимодействие требует знания обеих сторон интерфейса. Мы можем видеть только одну сторону.
  • 0
    1) Вам, вероятно, нужно либо заменить некоторые IntPtr на 32-битные целые, либо наоборот. Сравните определение этих структур в C и C # и определите правильные целочисленные размеры, используя таблицу в Типах данных Windows на MSDN . 2) Различия в выравнивании - еще одна потенциальная проблема, но она не должна влиять на ваш случай.
Показать ещё 6 комментариев
Теги:
struct
pinvoke
marshalling

2 ответа

0
Лучший ответ

Поскольку Ручки 64 бит на 64-битных сборках, а структура, которую мы получаем, по-прежнему содержит 32 бита. Изменение IntPtr на Uint32 для hIcon и hWnd сделало трюк. Теперь эта структура работает как на архитектуре x64, так и на x86. Я всегда знал, что сериализация в JSON определенно не соответствует моему требованию. Спасибо за помощь.

1

Эти структуры различаются для разных архитектур. Значения IntPtr имеют ширину 32 бит или ширину 64 бит в зависимости от архитектуры. Это имеет очевидные последствия для размера членов и, возможно, менее очевидных последствий для выравнивания.

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

Вы можете выбрать фиксированный макет, используя С# long вместо IntPtr. Такие типы, как HWND и HICON, всегда будут соответствовать long С#. Хотя будьте осторожны с типами дескрипторов, которые имеют смысл только в конкретном процессе. Например, значения HICON не будут иметь значения, как только вы отправите их в другой процесс.

Вместо использования фиксированной структуры компоновки, я думаю, я бы сериализовал. Сериализуйте данные, которые вы хотите отправить в JSON, например. Это может быть легко упаковано в строку и отправлено через WM_COPYDATA.

  • 0
    долгая помощь поможет моему делу.
  • 0
    Вы должны изменить структуру везде. Недостаточно изменить его только в коде C #. Вы должны также изменить неуправляемые структуры.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню