【问题标题】:C Hook/Callback SystemC挂钩/回调系统
【发布时间】:2012-03-04 03:05:32
【问题描述】:

我一直在试图弄清楚如何在 C 中实现一个钩子系统。谁能给我一些指点或例子?

【问题讨论】:

  • 这里有一个指针:void * (*)(void *).
  • dlopen ?考虑支持插件或扩展的应用程序,例如 apache http 服务器、lighttpd 或浏览器(例如 nsapi)
  • 不,那不是指针。那是语法垃圾。
  • @KerrekSB xkcd.com/138
  • @KerrekSB 我想有人会这么说.. xD

标签: c pointers callback hook


【解决方案1】:

使用函数指针:

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()
  • 第二种解决方案是我正在寻找的。我正在编写一个模块化的 IRC 守护程序,但不确定如何实现挂钩系统。谢谢!
  • @AaronThomasBlakely 没问题,请务必接受答案(点击答案旁边的复选标记)。
【解决方案2】:

您可以查看 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 需要一个函数指针作为排序的回调。

【讨论】:

    【解决方案3】:

    我不确定你到底在寻找什么,但我一直在使用 QT/C++ 中的钩子开发应用程序,所以我可以举几个小例子。

    首先,声明函数原型,像这样

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

    然后,您需要在 main 函数中设置挂钩,如下所示:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      • 2021-04-28
      相关资源
      最近更新 更多