Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的信号和回调?_C_Events_Event Handling_Callback_Signals - Fatal编程技术网

C语言中的信号和回调?

C语言中的信号和回调?,c,events,event-handling,callback,signals,C,Events,Event Handling,Callback,Signals,有没有办法在C中创建回调和信号 当然,我可以使用函数指针,但我想创建一个可以容纳多个函数的信号,即可以绑定到多个事件。类似于boost.signals的东西但是在C语言中。有办法吗 C中有许多gui库使用回调,它们是如何实现的?一个简单的解决方案是保留一个要调用的函数列表,在信号处理程序中,只需在该列表上迭代调用每个函数 大概是这样的: #include <stdio.h> #include <stdlib.h> #include <signal.h> #in

有没有办法在C中创建回调和信号

当然,我可以使用函数指针,但我想创建一个可以容纳多个函数的信号,即可以绑定到多个事件。类似于boost.signals的东西但是在C语言中。有办法吗


C中有许多gui库使用回调,它们是如何实现的?

一个简单的解决方案是保留一个要调用的函数列表,在信号处理程序中,只需在该列表上迭代调用每个函数

大概是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

typedef void (*event_callback_t)();

struct event_handler_node
{
    event_callback_t callback;
    struct event_handler_node *next;
};

void add_event_handler(struct event_handler_node **list_head,
                       event_callback_t callback)
{
    struct event_handler_node *node = malloc(sizeof(struct event_handler_node));

    node->callback = callback;
    if (*list_head != NULL)
        node->next = *list_head;
    *list_head = node;
}

void call_all_event_handlers(struct event_handler_node *list_head)
{
    struct event_handler_node *node;

    for (node = list_head; node != NULL; node = node->next)
    {
        (*node->callback)();
    }
}

struct event_handler_node *signal_callbacks = NULL;
void signal_handler(int signum)
{
    call_all_event_handlers(signal_callbacks);
}

void my_callback()
{
    printf("Hello from callback!\n");
}

int main()
{
    /* Add a callback to the list */
    add_event_handler(&signal_callbacks, my_callback);

    /* Set signal handler for a signal */
    signal(SIGUSR1, signal_handler);

    /* Invoke the signal handler */
    kill(getpid(), SIGUSR1);

    return 1;
}
#包括
#包括
#包括
#包括
typedef void(*event_callback_t)();
结构事件处理程序节点
{
事件回调\u t回调;
结构事件处理程序节点*下一步;
};
无效添加事件处理程序(结构事件处理程序节点**列表头,
事件_回调_t回调)
{
struct event_handler_node*node=malloc(sizeof(struct event_handler_node));
节点->回调=回调;
如果(*列表头!=空)
节点->下一步=*列表头;
*列表头=节点;
}
无效调用所有事件处理程序(结构事件处理程序节点*列表头)
{
结构事件处理程序节点*node;
对于(节点=列表头;节点!=NULL;节点=节点->下一步)
{
(*节点->回调)();
}
}
struct event\u handler\u node*signal\u callbacks=NULL;
无效信号处理器(内部信号)
{
调用所有事件处理程序(信号回调);
}
作废我的_回调()
{
printf(“来自回调的你好!\n”);
}
int main()
{
/*将回调添加到列表中*/
添加事件处理程序(&signal\u回调,my\u回调);
/*为信号设置信号处理程序*/
信号(SIGUSR1,信号处理器);
/*调用信号处理程序*/
kill(getpid(),SIGUSR1);
返回1;
}

注意:没有错误处理,也没有释放分配的内存。这是留给读者的练习。:-)

一个简单的解决方案是保留一个要调用的函数列表,在信号处理程序中,只需迭代该列表即可调用每个函数

大概是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

typedef void (*event_callback_t)();

struct event_handler_node
{
    event_callback_t callback;
    struct event_handler_node *next;
};

void add_event_handler(struct event_handler_node **list_head,
                       event_callback_t callback)
{
    struct event_handler_node *node = malloc(sizeof(struct event_handler_node));

    node->callback = callback;
    if (*list_head != NULL)
        node->next = *list_head;
    *list_head = node;
}

void call_all_event_handlers(struct event_handler_node *list_head)
{
    struct event_handler_node *node;

    for (node = list_head; node != NULL; node = node->next)
    {
        (*node->callback)();
    }
}

struct event_handler_node *signal_callbacks = NULL;
void signal_handler(int signum)
{
    call_all_event_handlers(signal_callbacks);
}

void my_callback()
{
    printf("Hello from callback!\n");
}

int main()
{
    /* Add a callback to the list */
    add_event_handler(&signal_callbacks, my_callback);

    /* Set signal handler for a signal */
    signal(SIGUSR1, signal_handler);

    /* Invoke the signal handler */
    kill(getpid(), SIGUSR1);

    return 1;
}
#包括
#包括
#包括
#包括
typedef void(*event_callback_t)();
结构事件处理程序节点
{
事件回调\u t回调;
结构事件处理程序节点*下一步;
};
无效添加事件处理程序(结构事件处理程序节点**列表头,
事件_回调_t回调)
{
struct event_handler_node*node=malloc(sizeof(struct event_handler_node));
节点->回调=回调;
如果(*列表头!=空)
节点->下一步=*列表头;
*列表头=节点;
}
无效调用所有事件处理程序(结构事件处理程序节点*列表头)
{
结构事件处理程序节点*node;
对于(节点=列表头;节点!=NULL;节点=节点->下一步)
{
(*节点->回调)();
}
}
struct event\u handler\u node*signal\u callbacks=NULL;
无效信号处理器(内部信号)
{
调用所有事件处理程序(信号回调);
}
作废我的_回调()
{
printf(“来自回调的你好!\n”);
}
int main()
{
/*将回调添加到列表中*/
添加事件处理程序(&signal\u回调,my\u回调);
/*为信号设置信号处理程序*/
信号(SIGUSR1,信号处理器);
/*调用信号处理程序*/
kill(getpid(),SIGUSR1);
返回1;
}

注意:没有错误处理,也没有释放分配的内存。这是留给读者的练习。:-)

正如Joachim所说,您应该保存函数指针列表。C中没有本机动态数组,但您可以自己实现:

struct list {
 void (*func)(void);
 struct list *next;
} *cb=NULL;
void add_callback(void (*f)(void)) {
 struct list *newCallback=(struct list *)malloc(sizeof(struct list));
 newCallback->func=f;
 newCallback->next=cb;
 cb=newCallback;
}
void call_callbacks() {
 struct list *t=cb;
 while (t) {
  (*(t->func))();
  t=t->next;
 }
}

正如Joachim所说,您应该保存函数指针列表。C中没有本机动态数组,但您可以自己实现:

struct list {
 void (*func)(void);
 struct list *next;
} *cb=NULL;
void add_callback(void (*f)(void)) {
 struct list *newCallback=(struct list *)malloc(sizeof(struct list));
 newCallback->func=f;
 newCallback->next=cb;
 cb=newCallback;
}
void call_callbacks() {
 struct list *t=cb;
 while (t) {
  (*(t->func))();
  t=t->next;
 }
}

但我不知道有多少函数将绑定到信号处理程序,因此我需要一个动态数组/列表。我认为C中没有动态数组,当然有。使用
malloc
realloc
可以非常轻松地实现动态数组。此外,没有任何东西可以阻止您编写自己的链表实现(在我看来,在这里更可取)@Daniel如果你使用的是基于unix的系统,你很可能可以使用
@mediatehacker用一个工作程序更新了我的答案。但是我不知道有多少函数将绑定到信号处理程序,所以我需要一个动态数组/列表。我认为C中没有动态数组,当然有。使用
malloc
realloc
可以非常轻松地实现动态数组。此外,没有任何东西可以阻止您编写自己的链表实现(在我看来,在这里更可取)@丹尼尔,如果你使用的是基于UNIX的系统,你可以使用<代码> <代码> @中间程序HAKER用工作程序更新我的答案。@ CODER02你已经提出了一个编辑,将变量从<代码>新< /代码>改为<代码> NealCalbBuff< /C> >,并将Maloc结果转换成-即,它将用C++编译器编译。注意,代码是有效的。然而,IMO无论如何都可以避免变量名为“代码>新<代码>。IIVC有些编译器拒绝它作为保留名称。”CODR02您已经提出了一个编辑,将变量从<代码>新< /代码>改为<代码> NealCalbBuff</C> >,并将Maloc结果转换为-C++,以使其能够用C++编译。编译器。请注意,代码原样是有效的C。但是,无论如何,在我看来,避免使用名为
new
的变量是值得的-IIRC一些编译器无论如何都会拒绝将其作为保留名称。