Доступ к объектному полю в функции ОБРАТНОГО вызова (WINAPI — C )

#c #class #winapi #callback

#c #класс #winapi #обратный вызов

Вопрос:

Я использую SetWinEventHook() функцию, подобную приведенной в примере MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640 (v=против85).aspx.
Как и в примере выше, для обработки событий я использую функцию ОБРАТНОГО ВЫЗОВА HandleWinEvent() .

Я довольно новичок в использовании функций такого типа: я понял, что эта функция вызывается
асинхронно, а параметры передаются автоматически.
Теперь я хочу получить доступ к списку внутри функции.
Я объявил эту функцию внутри своего класса:

 Class Example
{
private: std::list <int> events;
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, 
                             LONG idObject, LONG idChild, 
                             DWORD dwEventThread, DWORD dwmsEventTime) 
{
events.add((int)event);
};

void Initialize_Hook()
{
    cout << "Initialization Thread messages..........." << endl;
    CoInitialize(NULL);
    g_hook = SetWinEventHook(
        EVENT_SYSTEM_FOREGROUND, EVENT_OBJECT_FOCUS,  // Range of events (4 to 5).
        NULL,                                          // Handle to DLL.
        HandleWinEvent,                                // The callback.
        0, 0,              // Process and thread IDs of interest (0 = all)
        WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}
}
  

и я просто хочу добавить идентификатор события в свой список, но он не распознает events . Есть способ заставить функцию узнать, что это за список?

Более конкретно, я объявил функцию ОБРАТНОГО ВЫЗОВА в файле .cpp, но я должен объявить ее как void CALLBACK HandleWinEvent(...) вместо void CALLBACK Example::HandleWinEvent(...) , как я всегда делаю, потому что второй вариант выдает ошибку в SetWinEventHook() .

Комментарии:

1. Обратному вызову не разрешается быть методом экземпляра. Итак, спросите себя, где он собирается найти ваш экземпляр?

2. Я не знаю. Например, я могу передать через SetWinEventHook указатель на список, но я изобретаю (также потому, что в прототипе нет указателя для передачи). Как я могу это сделать?

3. Используйте либо thunk, либо единственную глобальную переменную, содержащую ваш экземпляр

4. Глобальная переменная для списка? Извините, но я не знаю, что означает thunk.

5. Google скажет вам, что такое thunk в этом контексте. По сути, вы генерируете код во время выполнения, который содержит указатель экземпляра.

Ответ №1:

Следуя подсказке, предоставленной @David Heffernan, я решил объявить список как static . Затем я написал статический метод для получения списка.
Таким образом, внутри функции ОБРАТНОГО вызова я мог бы получить ссылку на список:

 private: static std::list <int> events;
std::list <int>amp; getList() {
return *events;
}
// the callback is now declared in Example.cpp file
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, 
                             LONG idObject, LONG idChild, 
                             DWORD dwEventThread, DWORD dwmsEventTime) 
{
Example::getList().add((int)event);
};
  

(Я не пробовал с int , со списком Example2 класса сработало).