在c中设置一系列函数指针和回调

在c中设置一系列函数指针和回调,c,pointers,callback,function-pointers,C,Pointers,Callback,Function Pointers,我已经阅读了一些关于函数指针作为回调的不同SO答案,但是我自己在实现它时仍然有一些困难 像这样的问题: 这是: 还有其他一些 我不确定这是不是最好的办法 文件.h typedef int (*reg_callback)(void*, void*); //generalize a bit? int register_created(reg_callback cb); int register_fixed_update(reg_callback cb); int register_variable

我已经阅读了一些关于函数指针作为回调的不同SO答案,但是我自己在实现它时仍然有一些困难

像这样的问题:

这是:

还有其他一些

我不确定这是不是最好的办法

文件.h

typedef int (*reg_callback)(void*, void*); //generalize a bit?

int register_created(reg_callback cb);
int register_fixed_update(reg_callback cb);
int register_variable_update(reg_callback cb);
int register_render(reg_callback cb);
int register_pased(reg_callback cb);
int register_resume(reg_callback cb);
int register_resize(reg_callback cb);
int register_quit(reg_callback cb);

int init_engine(int width, int height, char *title, double fps);

//prototypes of functions that I need callbacks for atm maybe more soon
void created(void);
void fixed_update(void);
void variable_update(void);
void render(double alpha);
void paused(void);
void resumed(void);
void resized(int width, int height);
void quit(void);
文件.c

static int register_callback_function(int c_type, reg_callback cb)
{
    int success = -1;
    switch(c_type)
    {
        case 000000:
            printf("registering fixed update\n");
            break;
        case 000001:
            printf("registering variable update\n");
            break;
        case 000002:
            printf("registering render\n");
            break;
        case 000003:
            printf("registering pause\n");
            break;
        case 000004:
            printf("registering resume\n");
            break;
        case 000005:
            printf("registering resize\n");
            break;
        case 000006:
            printf("registering quit\n");
            break;
        default:break;
    }
    return success;
}
int register_fixed_update(reg_callback cb)     { return register_callback_function(000000, cb); };
int register_variable_update(reg_callback cb)  { return register_callback_function(000001, cb); };
int register_render(reg_callback cb)           { return register_callback_function(000002, cb); };
int register_pased(reg_callback cb)            { return register_callback_function(000003, cb); };
int register_resume(reg_callback cb)           { return register_callback_function(000004, cb); };
int register_resize(reg_callback cb)           { return register_callback_function(000005, cb); };
int register_quit(reg_callback cb)             { return register_callback_function(000006, cb); };
int register_created(reg_callback cb)          { return register_callback_function(000007, cb); };

void created(void)                  { //call create callback func }
void fixed_update(void)             { //call fixed update callback func}
void variable_update(void)          { //...}
void render(double alpha)           { //...}
void paused(void)                   { //...}
void resumed(void)                  { //...}
void resized(int width, int height) { //...}
void quit(void)                     { //...}
目前,我收到如下警告:

warning: incompatible pointer types passing 'void (void)' to parameter of
      type 'reg_callback' (aka 'int (*)(void *, void *)') [-Wincompatible-pointer-types]
    register_created(created);
                     ^~~~~~~
note: passing argument to parameter 'cb' here
int register_created(reg_callback cb);
不兼容的指针类型,但我认为void*指针可以指向任何东西,甚至什么都没有

我想概括函数指针,这样我就可以使用单指针原型来处理所有这些设置代码。从代码不起作用,我知道我走错了方向,我想修复它

可能有一个带有指向函数指针的结构,但我不确定atm。

我可以编译“gcc a.c”下面的代码,没有警告/错误。您将回调函数定义为“intfn(void*,void*)”。因此,回调函数应该实现为“intfn(void*p,void*q){}”

我将函数“fixed_update”更改为“int fixed_update(void*a,void*b){}”,以匹配回调函数定义的void error

我希望它能帮助你

#include <stdio.h>

typedef int (*reg_callback)(void*, void*);

static int register_callback_function(int c_type, reg_callback cb)
{
    int success = -1;
    switch(c_type)
    {
    case 000000:
        printf("registering fixed update\n");
        break;
    default:
        break;
    }
    return success;
}

int register_fixed_update(reg_callback cb)     {
    return register_callback_function(000000, cb);
};

int fixed_update(void *a, void *b) {
}

int main()
{
    register_fixed_update(fixed_update);

    return 0;
}
#包括
typedef int(*reg_回调)(无效*,无效*);
静态int寄存器回调函数(int c类型,reg回调cb)
{
int success=-1;
开关(c_型)
{
案例000000:
printf(“注册固定更新”);
打破
违约:
打破
}
回归成功;
}
整型寄存器\u固定\u更新(寄存器回调cb){
返回寄存器回调函数(000000,cb);
};
int固定更新(void*a,void*b){
}
int main()
{
寄存器固定更新(固定更新);
返回0;
}

在最初的评论和进一步的研究之后,我发现了一个运行良好的系统。下面是它的结构

函数指针结构

server.c
typedef struct
{
    void (*init_fnc_ptr)(void);
    void (*fixed_update_fnc_ptr)(void);
    void (*variable_update_fnc_ptr)(void);
    void (*render_fnc_ptr)(double alpha);
    void (*paused_fnc_ptr)(void);
    void (*resumed_fnc_ptr)(void);
    void (*resized_fnc_ptr)(int width, int height);
    void (*quit_fnc_ptr)(void);
} lfcyc_fnc_ptr;

lfcyc_fnc_ptr* lfc_f;

init() { lfc_f->init_fnc_ptr(); }
void fixed_update(void) { lfc_f->fixed_update_fnc_ptr(); }
//etc
以及一个函数,该函数采用以下函数指针结构之一。 在客户端代码中,我导入正确的头,然后初始化它

lfcyc_fnc_ptr* funcs = (lfcyc_fnc_ptr *)malloc(sizeof(lfcyc_fnc_ptr));
funcs->init_fnc_ptr = &initialized;
funcs->fixed_update_fnc_ptr = &fixed_update;
funcs->variable_update_fnc_ptr = &variable_update;
funcs->render_fnc_ptr = &render;
funcs->paused_fnc_ptr = &paused;
funcs->resumed_fnc_ptr = &resumed;
funcs->resized_fnc_ptr = &resized;
funcs->quit_fnc_ptr = &quit;

register functions(funcs);
//work
free(funcs);
然后,它将正确的地址传递给服务器函数,然后它可以在客户端代码中调用它需要的函数


我希望这能帮助将来遇到类似情况的人。

这比你想象的要简单得多。如果可能的话,我会尽量避免使用“register\u callback\u函数”。只需1)声明原型,2)定义您的实现,3)只需将您选择的任何函数(例如在运行时)分配给您的函数指针。这里有一个例子:顺便说一句,你意识到你的两个链接都指向同一个SO post吗?
void*
可以指向任何非函数数据类型。函数指针是特殊的,必须匹配正确的类型。感谢您的评论,尤其是@paulsm4的链接,它确实帮助我更好地澄清了一些问题。感谢这确实起了作用,但它揭示了一些问题,我不想只是传递空指针,尤其是当它们包含有用的内容时,从长远来看,可能会造成更多的麻烦。