There is a C++ snippet which has to use some old plain C event_handler functions.
The event_handler has this common signature:
add_event_handler(event_cb callback, void* user_data)
Note: event_cb
is a function pointer, probably unrelated to this question.
user_data
is defined to let the user to pass some extra information to the callback.
Now, my question is really simple, (how) can I pass a simple number as user_data?
add_event_handler(mycallback, 1); // compilation error
Obviously, because 1
is not a void*, but still, how can I pass some simple variable from the stack (not from heap)?
For example: is the below code considered correct?
int param=1;
add_event_handler(mycallback, ¶m);
Because this is working, but if I have to register more handlers, will look very ugly:
int param1=1;
int param2=2;
...
add_event_handler(mycallback, ¶m1);
add_event_handler(mycallback, ¶m2);
I just want to define the same callback for a bunch of events and give them an integer or enum value as user_data to decide about the necessary action in mycallback.
Here is mycallback:
static void mycallback(void* user_data) {
// do an action based on user_data, ie: if 1 passed, print "one", if 2 print "two".
}
Please note: I've tried searching for these kind of things, but void*
topic is huge, and Google was not that smart to understand my wishes. Sorry if there is another question here with the same topic, I haven't found that either. In this case please just post it, and mark this as duplicate.
If (and only if) the user_data
pointer isn't used elsewhere, you can use casting to convert any integer whose sizeof
is smaller than (or equal to) sizeof(void*)
to a void*
type.
However, to be fully compliant you can't do the cast in a single step, it has to be done over an intermediate cast:
add_event_handler(mycallback, reinterpret_cast<void*>(static_cast<intptr_t>(1)));
To be able to use this you need to do the opposite casting:
static void mycallback(void* user_data) {
int value = static_cast<int>(reinterpret_cast<intptr_t>(user_data));
}
Casting like this is usually considered bad, but in some cases (like the one you have) it's really the only possible way to pass plain integer values.
[Note that on a 32-bit system with 32-bit pointers, a 64-bit integer type like long long
can't be passed this way]
The other solution is, as you noted in your question, to use separate variables (or possibly dynamically allocated values) to be able to pass actual pointers.