Могу ли я использовать WM_COPYDATA для копирования неструктуры? - PullRequest
0 голосов
/ 31 октября 2009

Допустим, у меня есть этот класс в foobar-shared.lib:

class FooBar {
    std::string m_helloWorld;
}

И у меня есть вызов в foobar-from.exe с использованием SendCopyData, например, так:

extern HWND hMainWnd; // foobar-from.exe

{
FooBar fooBar;

HWND hWnd = FindAppWindow(); // foobar-to.exe
COPYDATASTRUCT cds;
cds.dwData = ('f'|('o'<<8)|('o'<<16));
cds.cbData = sizeof(FooBar);
cds.lpData = (LPVOID)fooBar;
SendCopyData(hWnd, (WPARAM)hMainWnd, (LPARAM)&cds);
}

Когда из foobar-to.exe я обрабатываю OnCopyData:

BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) {
    if (pCopyDataStruct->dwData==('f'|('o'<<8)|('o'<<16))) {
        FooBar fooBar = *(FooBar *)pCopyDataStruct->lpData;
    }
}

Это работало нормально, когда FooBar был структурой, но теперь, когда это класс, я получаю эту ошибку:

First-chance exception at 0x0064ef81 in foobar-to.exe: 0xC0000005: 
Access violation reading location 0x0231dd7c.

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

Согласно MSDN , «передаваемые данные не должны содержать указателей или других ссылок на объекты, недоступные для приложения, получающего данные». так что я подозреваю, что это возможно только с данными структуры. Я прав?

1 Ответ

2 голосов
/ 31 октября 2009

вы оба правы и неверны.

Ваша проблема здесь в том, что вы не знаете деталей реализации std :: string. к сожалению, кажется, что этот (стандартный) класс использует динамически выделенный буфер для хранения своих символьных данных. вот почему WM_COPYDATA не работает с ним.

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

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

...