2012-03-03 10 views
1

私はCでフックシステムを実装する方法を理解しようとしてきた誰も私にいくつかのポインタかの例を与えることができますか?Cフック/コールバックシステム

+3

ここにポインタがあります: 'void *(*)(void *)'。 –

+0

dlopen?いいえ、それはポインタでないプラグインや拡張機能をサポートするアプリケーションは、そのようなApache HTTPサーバ、lighttpdの、またはブラウザ(例:NSAPI) – qrtt1

+1

を考えてみましょう。これは構文上のゴミです。 – Swiss

答えて

2

使用関数ポインタ:

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

多かれ少なかれ一般的なコールバックシステムでは、コンテキストを提供するボイドポインタ引数は非常に有用です。そのような文脈のないもの(例えば、 'qsort()')は、 'qsort()'で文脈を必要とするのは誰もが問題ではないと証明することができます。 [ 'qsort_r()'](https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/qsort_r.3.html)を参照してください。 –

+0

第2の解決策は私が探しているものです。私はモジュール式のIRCデーモンを作成しており、フックシステムの実装方法がわかりませんでした。ありがとう! –

+0

@AaronThomasBlakely問題ありません、単に解答(解答の横にあるチェックマークをクリック)を受け入れるようにしてください。 –

0

あなたはの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は、ソートするためのコールバックで関数ポインタを必要としています。

0

イムないuは、正確に探しているが、IVEはQT/C++でのフックを使用してアプリケーションを開発してきたので、私はあなたに少し例を与えることができるか確認してください。

HHOOK mouseHook; 
HINSTANCE appInstance = GetModuleHandle(NULL); 
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, appInstance, 0); //set global mouse hook 

をし、その後、あなたはコールバック関数を定義する必要があります。

まず、この

LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam); 

のように、関数のプロトタイプを宣言し、あなたはこのように、主な機能には、フックを設定する必要がありますあなたに私のコードを与えることができます>

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

}