c - C 中的函数指针和回调

标签 c function pointers callback

我已经开始审查回调。我在 SO 上找到了这个链接: What is a "callback" in C and how are they implemented?它有一个很好的回调示例,与我们在工作中使用的非常相似。然而,我试图让它工作,但我有很多错误。

#include <stdio.h>

/* Is the actual function pointer? */
typedef void (*event_cb_t)(const struct event *evt, void *user_data);

struct event_cb
{
    event_cb_t cb;
    void *data;
};

int event_cb_register(event_ct_t cb, void *user_data);

static void my_event_cb(const struct event *evt, void *data)
{
    /* do some stuff */
}

int main(void)
{
    event_cb_register(my_event_cb, &my_custom_data);

    struct event_cb *callback;

    callback->cb(event, callback->data);

    return 0;
}

我知道回调使用函数指针来存储函数的地址。但是有几件事我发现我不明白:

  • “注册回调”和“事件调度程序”是什么意思?

最佳答案

此代码使用 -Wall 在 GCC 下编译和运行。

#include <stdio.h>

struct event_cb;

typedef void (*event_cb_t)(const struct event_cb *evt, void *user_data);

struct event_cb
{
    event_cb_t cb;
    void *data;
};

static struct event_cb saved = { 0, 0 };

void event_cb_register(event_cb_t cb, void *user_data)
{
    saved.cb = cb;
    saved.data = user_data;
}

static void my_event_cb(const struct event_cb *evt, void *data)
{
    printf("in %s\n", __func__);
    printf("data1: %s\n", (const char *)data);
    printf("data2: %s\n", (const char *)evt->data);
}

int main(void)
{
    char my_custom_data[40] = "Hello!";
    event_cb_register(my_event_cb, my_custom_data);

    saved.cb(&saved, saved.data);

    return 0;
}

您可能需要检查回调函数是否获取了整个 struct event_cb - 通常,您只是传递数据,因为如前所述,否则您有相同信息的两个来源(以及指向您所在函数的指针)。可以对此进行大量清理 - 但它确实有效。


评论中的一个问题是:这是回调的一个很好的例子吗?

简而言之,没有 - 但部分原因是这里没有足够的基础设施。

在某种意义上,您可以将传递给qsort()bsearch() 函数的比较函数视为回调。它是一个指向传递给泛型函数的函数的指针,泛型函数可以完成泛型函数自身不能做的事情。

回调的另一个例子是信号处理函数。您告诉系统在事件(信号)发生时调用您的函数。您提前设置机制,以便当系统需要调用一个函数时,它知道要调用哪个函数。

示例代码试图提供一种更精细的机制 - 带有上下文的回调。在 C++ 中,这可能是一个仿函数。

我使用的一些代码对内存管理有非常挑剔的要求 - 当在特定上下文中使用时。因此,对于测试,我使用 malloc() 等,但在生产中,我必须将内存分配器设置为专用分配器。然后我在包中提供了一个函数调用,这样繁琐的代码就可以用它自己的代理版本覆盖默认的内存分配器——如果代理工作正常,代码将像以前一样运行。这些是回调的一种形式 - 同样,一种不需要太多(或任何东西)用户上下文数据的形式。

窗口系统具有已注册的事件处理程序(回调),GUI 主事件循环将在事件发生时调用。这些通常需要用户上下文以及 GUI 系统提供的特定于事件的信息。

关于c - C 中的函数指针和回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/631273/

相关文章:

c++ - static_cast const 引用 void*

c - 数组名是指针吗?

arrays - Maxima:定义一个函数,返回一个范围内的随机整数,使得该值不同于另一个值或其他值的列表

r - 构建函数以将自然中断 jenks 应用于我的 df 列时出错

c - gcc错误编译文件

c - 多次调用时在函数中存储值

r - 通过一个问题计算 R 和 off 中两个值之间的百分比变化

c - 为什么 puts() 函数中的指针在以下代码的第 4 行中不起作用?虽然第 1 行正在运行

c++ - 内核模式 - 通过共享内存进行用户模式通信,无需使用系统线程

c - Sscanf 和自定义中断