Я пытался выяснить, как реализовать систему крючков в C. Может ли кто-нибудь дать мне несколько указателей или примеров?C Hook/Callback System
ответ
Использование указателей на функции:
struct callbacks {
void (*somethingHappened)(void *context);
bool (*shouldIDoSomething)(void *context);
};
void doSomethingAwesome(void *operationData, struct callbacks callbacks)
{
// context is the data you pass to the function
if (callbacks.shouldIDoSomething(context))
{
// do something
callbacks.somethingHappened(context);
}
}
В качестве альтернативы, вы можете создать диспетчерскую службу:
struct dictionary
{
char **keys;
void **values;
int count;
};
struct list
{
void **values;
int count;
};
// functions to add, remove, etc;
struct dictionary *callbacks = NULL;
void registerForDispatch(char *key, void (*callback)(void *))
{
if (!callbacks)
{
callbacks = dictionary_create(10); // dictionary with 10 key/value pairs
}
if (!dictionary_containsKey(callbacks, key))
{
struct list *callBacksForKey = list_create(10); // default 10 callbacks, array should be auto-expanding
dictionary_setValue(callbacks, key, arr);
}
struct list *callBacksForKey = dictionary_getValue(callbacks, key);
list_addObject(callBacksForKey, callback);
}
void unregisterFromDispatch(char *key, void (*callback)(void *))
{
struct list *callBacksForKey = dictionary_getValue(callbacks, key);
list_removeObject(callback);
}
void sendNotification(char *key, void *context)
{
struct list *callBacksForKey = dictionary_getValue(callbacks, key);
for (int i = 0; list->count; i++)
{
void (*callback)(void *) = list->values[i];
callback(context);
}
}
Во втором варианте, у вас есть преимущество нескольких слушателей для одного обратного вызова.
Для более или менее общей системы обратного вызова очень полезен аргумент аргумента указателя void. Те, у кого такой контекст (например, 'qsort()'), могут оказаться проблематичными - хотя не каждому нужен контекст с 'qsort()'. См. ['Qsort_r()'] (https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/qsort_r.3.html). –
Второе решение - это то, что я ищу. Я пишу модульный демон IRC и не был уверен, как реализовать систему крючков. Благодаря! –
@AaronThomasBlakely Нет проблем, просто не забудьте принять ответ (нажмите галочку рядом с ответом). –
Вы можете увидеть QSort примера: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
/* qsort example */
#include <stdio.h>
#include <stdlib.h>
int values[] = { 40, 10, 100, 90, 20, 25 };
int compare (const void * a, const void * b)
{
return (*(int*)a - *(int*)b);
}
int main()
{
int n;
qsort (values, 6, sizeof(int), compare);
for (n=0; n<6; n++)
printf ("%d ",values[n]);
return 0;
}
QSort нужен указатель на функцию, которая является обратным вызовом для сортировки.
Я не уверен, что вы ищете точно, но ive разрабатывает приложение с помощью крючков в QT/C++, поэтому я могу привести небольшой пример.
Во-первых, объявить прототип функции, как этот
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
то, что вам нужно установить крюк в основной функции, например:
HHOOK mouseHook;
HINSTANCE appInstance = GetModuleHandle(NULL);
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, appInstance, 0); //set global mouse hook
, а затем вам нужно определить функцию обратного вызова , я могу дать вам код мой>
//Mouse hook callback function.
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam){
if (nCode == HC_ACTION) {
switch(wParam){
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MOUSEWHEEL:
#ifdef DEBUG
w->printText("Scrolling or click");
#endif
w->save_key("MOUSE");
i++;
break;
default: break;
}
}
return CallNextHookEx(mouseHook, nCode, wParam, lParam);
}
Здесь находится указатель: 'void * (*) (void *)'. –
dlopen? Рассмотрим приложение, поддерживающее плагин или расширение, такой сервер apache http, lighttpd или браузеры (например, nsapi). – qrtt1
Нет, это не указатель. Это синтаксический мусор. – Swiss