C Крюк / Система обратного вызова - PullRequest
1 голос
/ 03 марта 2012

Я пытался выяснить, как реализовать систему перехватчиков в C. Кто-нибудь может дать мне несколько советов или примеров?

Ответы [ 3 ]

3 голосов
/ 03 марта 2012

Используйте указатели функций:

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);
    }
}

Во втором решении вы получаете преимущество нескольких слушателей для одного обратного вызова.

0 голосов
/ 03 марта 2012

Я не уверен, что именно вы ищете, но я разрабатывал приложение с использованием хуков, в 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);

}
0 голосов
/ 03 марта 2012

Вы можете увидеть пример 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 нужен указатель функции, который является обратным вызовом для сортировки.

...