Summary of answer: app_timer_register passes a pointer without type. To pass an integer, create an integer and pass it's pointer. Then type the pointer to integer.
example of using the untyped pointer:
static void timeHandler(void * untyped_pointer_to_an_integer){
function_requiring_integer((int)untyped_pointer_to_an_intergger);
I'm trying to pass an integer along with the code called by app_time_register. When I try the following:
static void time_handler(int val){
app_timer_register(wait_time_ms, time_handler, 1);
do_stuff();
}
I get the error:
../src/main.c:88:3: error: passing argument 2 of 'app_timer_register' from incompatible pointer type [-Werror]
In file included from ../src/main.c:1:0:
/app/sdk3/pebble/chalk/include/pebble.h:2656:11: note: expected 'AppTimerCallback' but argument is of type 'void (*)(int)'
../src/main.c:88:3: error: passing argument 3 of 'app_timer_register' makes pointer from integer without a cast [-Werror]
In file included from ../src/main.c:1:0:
/app/sdk3/pebble/chalk/include/pebble.h:2656:11: note: expected 'void *' but argument is of type 'int'
Pebble provides the following information about app_time_register (source https://developer.pebble.com/docs/c/Foundation/Timer/).
AppTimer * app_timer_register(uint32_t timeout_ms, AppTimerCallback callback, void * callback_data)
Registers a timer that ends up in callback being called some specified time in the future.
Parameters
timeout_ms
The expiry time in milliseconds from the current time
callback
The callback that gets called at expiry time
callback_data
The data that will be passed to callback
typedef void(* AppTimerCallback)(void *data)
The type of function which can be called when a timer fires. The argument will be the callback_data passed to app_timer_register().
I need helping figuring out how to use the callback_data to pass an integer.
Figure out what's wrong
Well, both the documentation and the error is very explicit:
app_timer_registerhas the signature:Thus, when calling it, you need to pass an
uint32_tas first, anAppTimerCallbackas second and a pointer to void (void *) as third argument.You call it with ...
... a
wait_time_ms(which is apparently fine), a pointer to the functiontime_handler(which is of typevoid (*)(int)) and an integer (which your compiler - rightfully - does not want to convert to avoid *pointer).Looking up the documentation,
AppTimerCallbackis basically a typedef for a (pointer to) function taking a void pointer as single argument, or more explicit:void (*)(void *)As you see, the types of argument 2 (
void (*)(int)vs the expectedvoid (*)(void *)) and argument 3 (intvs the expectedvoid *) do not match.Think about how it needs to be changed and why
The reason to have
void *as third argument (and as argument for the callback function) is to be able to pass arbitrary data to the callback function (as avoid *can point to everything).This is a idiom often found in C APIs that provide callbacks, it covers up the lack of closures of the language.
That arbitrary data is most often packed up in a structure (though a single integer - like in your case - could also be "smuggled" as pointer, but this is not scale-able and more over implementation defined):
Thus, your callback needs to look something like ...
... and when you register the callback, you need to actually provide memory for such a structure:
Note that using heap allocated memory is of course not mandatory, you could also use memory with static ("globals") or automatic ("stack") storage.
Finally
Registering a callback inside the callback itself is probably (I haven't looked into the documentation) not the way it's intended to be. Normally it's more like ...
... and having no call to
app_timer_registerin the actual callback (time_handler).