user1610950
user1610950

Reputation: 1917

setup a series function pointers and callbacks in c

I've read a few different SO answers on function pointers as callbacks but I am still having some trouble implementing it myself.

Questions like this: How do function pointers in C work?

and this: Understanding typedefs for function pointers in C

and a few others.

I am not sure if this is the best way to go about it.

file.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);

file.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)                     { //...}

currently I am getting a warning like these:

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

incompatibile pointer types but I though that void* pointers could point to anything, even nothing?

I wanted to generalize the function pointer so that I could just use the one pointer prototype to handle all this setup code. From the code not working I know I am going about it the wrong way and would like to fix that.

maybe have a struct with some pointer to functions but I am not sure atm.

Upvotes: 2

Views: 91

Answers (2)

user1610950
user1610950

Reputation: 1917

After the initial comments and some more research I found a system that worked pretty well. Here's how it's structured.

function pointer struct

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

and a function that takes one of these function pointer struct. In the client code I import the proper header and then initialize it;

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

this then passes the correct address to the server function then it can call the functions that it needs to in the client code.

I hope this is able to assist someone if they encounter something like this in the future.

Upvotes: 1

Wei Shao
Wei Shao

Reputation: 51

I can compile "gcc a.c" the follow code without warning/error. You defined you call back function as "int fn(void *, void *)". So your call back function should implement as "int fn(void *p, void *q){}"

I change the function "fixed_update" into "int fixed_update(void *a, void *b) {}" to match you callback function define to void error.

I hope it will help you.

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

Upvotes: 1

Related Questions