如何将 void* 转换为函数指针?
How to cast void* to a function pointer?
我在 FreeRTOS 中使用 xTaskCreate,它的第 4 个参数 (void * const) 是传递给新线程调用的函数的参数。
void __connect_to_foo(void * const task_params) {
void (*on_connected)(void);
on_connected = (void) (*task_params);
on_connected();
}
void connect_to_foo(void (*on_connected)(void)) {
// Start thread
xTaskCreate(
&__connect_to_foo,
"ConnectTask",
STACK_SIZE,
(void*) on_connected, // params
TASK_PRIORITY,
NULL // Handle to the created Task - we don't need it.
);
}
我需要能够传入带有签名的函数指针
void bar();
但我不知道如何将 void* 强制转换为我可以调用的函数指针。我能得到的最接近的是:
error: 'void*' is not a pointer-to-object type on line 3
如何将 task_params 转换为可以调用的函数指针?
注意上面的代码已经大大简化了。
大致如下:
typedef void (*OnConnected_t)();
OnConnected_t on_connected = OnConnected_t(task_params);
on_connected();
有一种可移植的直接转换替代方法。指向函数指针的指针本身就是数据指针。也就是说,给定auto connect_to_foo_ptr = &__connect_to_foo
,void* ptr = &connect_to_foo_ptr
处处合法
当然,要调用它,您需要将 void*
转换回 void (**)(void * const task_params)
,并取消引用它两次。第一次解引用让你回到函数指针,第二个解引用让你得到原来的函数。
这里的一个限制是您需要确保 connect_to_foo_ptr
不会超出范围,但这通常不是问题。您通常可以做到 static
,但即使是普通回调模式也不需要。
我在 FreeRTOS 中使用 xTaskCreate,它的第 4 个参数 (void * const) 是传递给新线程调用的函数的参数。
void __connect_to_foo(void * const task_params) {
void (*on_connected)(void);
on_connected = (void) (*task_params);
on_connected();
}
void connect_to_foo(void (*on_connected)(void)) {
// Start thread
xTaskCreate(
&__connect_to_foo,
"ConnectTask",
STACK_SIZE,
(void*) on_connected, // params
TASK_PRIORITY,
NULL // Handle to the created Task - we don't need it.
);
}
我需要能够传入带有签名的函数指针
void bar();
但我不知道如何将 void* 强制转换为我可以调用的函数指针。我能得到的最接近的是:
error: 'void*' is not a pointer-to-object type on line 3
如何将 task_params 转换为可以调用的函数指针?
注意上面的代码已经大大简化了。
大致如下:
typedef void (*OnConnected_t)();
OnConnected_t on_connected = OnConnected_t(task_params);
on_connected();
有一种可移植的直接转换替代方法。指向函数指针的指针本身就是数据指针。也就是说,给定auto connect_to_foo_ptr = &__connect_to_foo
,void* ptr = &connect_to_foo_ptr
处处合法
当然,要调用它,您需要将 void*
转换回 void (**)(void * const task_params)
,并取消引用它两次。第一次解引用让你回到函数指针,第二个解引用让你得到原来的函数。
这里的一个限制是您需要确保 connect_to_foo_ptr
不会超出范围,但这通常不是问题。您通常可以做到 static
,但即使是普通回调模式也不需要。