I want to detect if a value of a void* type input function argument is an integer or a pointer. Currently, I'm passing the integer only (this is Midnight Commander source):
mc_event_raise (MCEVENT_GROUP_CORE,
"clipboard_file_from_ext_clip",
(void*)(intptr_t)clip_id);
However I would also like to sometimes pass a string (char *) in the same parameter, as extending the API would be difficult. I know that this is wrong, however, maybe there is a fully legal way to obtain such effect ? My ideas:
– the addresses are in general aligned to 4 or 8 bytes, so I've could skip such values from the clip_id (jump over them) and then decode the value? if (data % 8) then clip_id = decode_clip_id(data);
?
– maybe pointers cannot be as small as 10…20 and a simple check would be sufficient?
– other ideas…?
A problem like this can be solved with a structure containing a union and a tag.
struct EventData {
enum { EV_IS_INT, EV_IS_PTR } type;
union {
intptr_t v_int;
void * v_ptr;
};
};
So, you can then pass a pointer to this EventData
, and the callback can decode whether to access v_int
or v_ptr
, based on the value of type
.
struct EventData *ed = makeEventData (EV_IS_INT, clip_id);
mc_event_raise (MCEVENT_GROUP_CORE,
"clipboard_file_from_ext_clip",
ed);
If the event is completed asynchronously, you may need to create the event dynamically, and then the callback function would have to release the memory when the callback is done with the argument.