C Pebble:如何使用app\u timer\u寄存器将整数作为回调数据传递?

C Pebble:如何使用app\u timer\u寄存器将整数作为回调数据传递?,c,pebble-watch,pebble-sdk,C,Pebble Watch,Pebble Sdk,答复摘要: app\u timer\u寄存器传递不带类型的指针。 要传递整数,请创建一个整数并传递其指针。 然后键入指向整数的指针 使用非类型指针的示例: static void timeHandler(void * untyped_pointer_to_an_integer){ function_requiring_integer((int)untyped_pointer_to_an_intergger); 我试图传递一个整数和app\u time\u register调用的代码。 当

答复摘要: app\u timer\u寄存器传递不带类型的指针。 要传递整数,请创建一个整数并传递其指针。 然后键入指向整数的指针

使用非类型指针的示例:

static void timeHandler(void * untyped_pointer_to_an_integer){
  function_requiring_integer((int)untyped_pointer_to_an_intergger); 
我试图传递一个整数和app\u time\u register调用的代码。 当我尝试以下方法时:

static void time_handler(int val){ 
  app_timer_register(wait_time_ms, time_handler, 1);
  do_stuff(); 
}
我得到一个错误:

../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提供了关于应用程序时间寄存器(源)的以下信息


我需要帮助了解如何使用回调数据传递整数。

错误消息告诉您
void(*)(int)
void(*)(void*data)
不兼容

相反,参数应为适当的类型:

static void time_handler(void *val) { 
  app_timer_register(wait_time_ms, time_handler, 1);
  do_stuff(); 
}

如果需要将整数传递给
时间处理程序
,请为其分配空间并传递指针。将整数强制转换为void*和back也是可能的,但不管它是否有效,都是实现定义的行为。它在ARM上工作(ARM ABI指定
sizeof(int)==sizeof(void*)和&&u Alignof(int)==u Alignof(void*)

错误消息告诉您
void(*)(int)
void(*)(void*数据)
不兼容

相反,参数应为适当的类型:

static void time_handler(void *val) { 
  app_timer_register(wait_time_ms, time_handler, 1);
  do_stuff(); 
}
如果需要将整数传递给
时间处理程序
,请为其分配空间并传递指针。将整数强制转换为void*和back也是可能的,但不管它是否有效,都是实现定义的行为。它在ARM上工作(ARM ABI指定
sizeof(int)==sizeof(void*)和&&u Alignof(int)==\u Alignof(void*)
)。

找出问题所在 文档和错误都非常明确:
app\u timer\u register
有签名:

AppTimer * app_timer_register(uint32_t, AppTimerCallback, void *);
因此,在调用它时,需要将
uint32\t
作为第一个参数传递,将
AppTimerCallback
作为第二个参数传递,并将指向void(
void*
)的指针作为第三个参数传递

你称之为

app_timer_register(wait_time_ms, time_handler, 1);
。。。一个
wait\u time\u ms
(这显然很好)、一个指向函数
time\u处理程序的指针(类型为
void(*)(int)
)和一个整数(您的编译器不希望将其转换为
void*
指针)

查阅文档,
AppTimerCallback
基本上是一个(指针指向)函数的类型定义,该函数将一个空指针作为单个参数,或者更明确地说:
void(*)(void*)

如您所见,参数2(
void(*)(int)
与预期的
void(*)(void*)
)和参数3(
int
与预期的
void*
)的类型不匹配


想想它需要如何改变,为什么要改变 将
void*
作为第三个参数(以及回调函数的参数)的原因是能够将任意数据传递给回调函数(因为
void*
可以指向所有内容)

这是一个常见于提供回调的C API中的习惯用法,它掩盖了语言闭包的不足

任意数据通常被打包在一个结构中(尽管单个整数(就像您的例子一样)也可以作为指针“走私”,但这是不可伸缩的,而且更多的是过度实现定义的):

因此,您的回调需要看起来像

void time_handler(void * passed) {
  struct time_handler_data * data = passed;
  // ... do stuff with data->val
}
。。。当您注册回调时,实际上需要为这样的结构提供内存:

struct time_handler_data * data = malloc(sizeof(*data));
// data->val = a fancy value to be used in time_handler
// also check if data != NULL!
AppTimer * you_certainly_need_this =
  app_timer_register(what_ever, &time_handler, data);
// DO NOT FORGET TO free(data) WHEN YOU UNREGISTER THE CALLBACK!
请注意,使用堆分配的内存当然不是强制性的,您也可以将内存用于静态(“全局”)或自动(“堆栈”)存储


最后 在回调本身中注册回调可能不是预期的方式(我没有查看文档)。通常它更像是

void /* or not */ register_time_handler(/* fancy arguments */)
{
   // code calling app_timer_register from above
}
。。。在实际回调(
time\u handler
)中没有调用
app\u timer\u register

找出问题所在 文档和错误都非常明确:
app\u timer\u register
有签名:

AppTimer * app_timer_register(uint32_t, AppTimerCallback, void *);
因此,在调用它时,需要将
uint32\t
作为第一个参数传递,将
AppTimerCallback
作为第二个参数传递,并将指向void(
void*
)的指针作为第三个参数传递

你称之为

app_timer_register(wait_time_ms, time_handler, 1);
。。。一个
wait\u time\u ms
(这显然很好)、一个指向函数
time\u处理程序的指针(类型为
void(*)(int)
)和一个整数(您的编译器不希望将其转换为
void*
指针)

查阅文档,
AppTimerCallback
基本上是一个(指针指向)函数的类型定义,该函数将一个空指针作为单个参数,或者更明确地说:
void(*)(void*)

如您所见,参数2(
void(*)(int)
与预期的
void(*)(void*)
)和参数3(
int
与预期的
void*
)的类型不匹配


想想它需要如何改变,为什么要改变 将
void*
作为第三个参数(以及回调函数的参数)的原因是能够将任意数据传递给回调函数(因为
void*
可以指向所有内容)

这是一个常见于提供回调的C API中的习惯用法,它掩盖了语言闭包的不足

任意数据通常被打包在一个结构中(尽管单个整数(就像您的例子一样)也可以作为指针“走私”,但这是不可伸缩的,而且更多的是过度实现定义的):

因此,您的回调需要看起来像

void time_handler(void * passed) {
  struct time_handler_data * data = passed;
  // ... do stuff with data->val
}
。。。当您注册回调时,实际上需要为这样的结构提供内存:

struct time_handler_data * data = malloc(sizeof(*data));
// data->val = a fancy value to be used in time_handler
// also check if data != NULL!
AppTimer * you_certainly_need_this =
  app_timer_register(what_ever, &time_handler, data);
// DO NOT FORGET TO free(data) WHEN YOU UNREGISTER THE CALLBACK!
请注意,使用堆分配的内存当然不是强制性的,您也可以将内存用于静态(“全局”)或自动(“堆栈”)存储


最后 在回调本身内部注册回调