Reputation: 2097
Hello guys I'm currently facing a pretty annoying problem:
I'm writing a system of callback manager that works by using function pointers, now given the fact that far now I've been assigned void function pointers to some other non-void function pointers, I've realized that it's not actually allowed in C.
At the moment I'm thinking about casting the void pointer so that matches the prototype function I have for my each callback, but I cannot understand how to implement the casting.
Would it be viable or should I adopt another solution?
Currently these are my callback containers and their typedefs:
typedef void modbus_read_t(unsigned int uid, unsigned int address, unsigned int count, char* response);
typedef void modbus_write_t(unsigned int uid, unsigned int address, unsigned int *data, char* response);
typedef void system_read_t(unsigned int uid, unsigned int var_number, unsigned int count, char* response);
typedef void system_write_t(unsigned int uid, unsigned int var_number, struttura_system *storage, char* response );
void (*M_callbacks_r[3]) (unsigned int uid, unsigned int address, unsigned int count, char* response);
void (*M_callbacks_w[2]) (unsigned int uid, unsigned int address, unsigned int *data, char* response);
void (*P_callbacks_r[2]) (unsigned int uid, unsigned int var_number, unsigned int count, char* response);
void (*P_callbacks_w[2]) (unsigned int uid, unsigned int var_number, struttura_system *storage, char* response );
This is the prototype of the function that registers the callback:
void registerCallback(int systemType,int operationType, void (callback)(void*));
What has to be done is to cast void (callback)(void*)
to one of the typedefs above.
Upvotes: 2
Views: 1356
Reputation: 170045
Well, casting should work. The C standard allows casting between function pointer types, the only thing you shouldn't do is call a function by a function pointer that has the wrong prototype, i.e. cast back to the correct prototype before the call, in order to avoid undefined behavior.
Let's start by simplifying your arrays a little, for readability sake:
modbus_read_t* M_callbacks_r[2];
modbus_write_t* M_callbacks_w[2];
system_read_t* P_callbacks_r[2];
system_write_t* P_callbacks_w[2];
I don't know why you typedef
ed the function type instead of the function pointer type, but I'll go along with it.
Now registerCallback
can be implemented as follows:
void registerCallback(int systemType,int operationType, void (*callback)()) {
// .. determine array by system type and operation type
M_callbacks_r[0] = (modbus_read_t*)callback;
}
The reason I deleted the parameter from the callback
prototype, is that in standard C, an empty parameter list conveys no information about the expected parameters (as opposed to C++ where it explicitly means "no parameters"). That way callbacks can be registered without requiring a cast.
As you mentioned in the comments, you are building with -Wstrict-prototypes -Werror
. So an empty parameter list will not work for you. You are thus restricted to defining registerCallback
like this:
void registerCallback(int systemType,int operationType, void (*callback)(void))
Note the explicit void
in the parameter list. You will need to cast the callback when passing it to registerCallback
as well as casting it back inside the function itself.
registerCallback(type, op, (void(*)(void))func_cb);
Side note: The _t
postfix is reserved on POSIX systems. To be portable, it may be best not to name your types with it.
Upvotes: 2