环绕一个 C 函数,该函数在 C++ 中使用 void* 接受其参数
Wrapping around a C function that takes its arguments with void* in C++
我正在包装来自 freeRTOS 的 C 函数,它创建一个任务并在 C++ 中使用 void 指针获取其参数。该函数看起来有点像这样:
void createTask(TaskFunction_t taskCode, void * args);
据我所知,要将 2 个参数传递给任务,我需要创建一个结构,将其地址转换为 void*,传递它,然后将其转换回原始状态,如下所示:
struct Params
{
const int a;
const double b;
};
static void task(void * args)
{
auto params = *static_cast<Params*>(args);
// do something with params.a and params.b
}
int main()
{
Params params{1, 2.2};
createTask(task, static_cast<void*>(¶ms));
}
包装此函数的首选方式是什么,以便我可以传递可变类型的可变数量的参数?我应该只留下 void * args 作为参数,还是可以用模板或元组来做一些事情来稍微简化这个过程。
从 C++11 开始,你可以使用类似
的东西
static void call_task(void *args) {
auto& f = *static_cast<std::function<void()>*>(args);
f();
}
// note: need this to stay alive!
std::function<void()> f = [&](){
// Any arguments you like here
do_whatever(1, 2, 3)
};
CreateTask(call_task, static_cast<void*>(&f));
您需要确保 f
的生命周期长于任务的生命周期(就像您对 Params
对象所做的那样)。
您实际上可以完全避免 std::function
,因为:
template<typename Func>
void call_func(void *args) {
auto& f = *static_cast<Func*>(args);
f();
}
template<typename Func>
void wrapped_create_task(Func& func) {
CreateTask(call_func<Func>, static_cast<void*>(&func));
}
// you can still use `std::function` here, but you don't have to.
auto f = [&](){
// Any arguments you like here
do_whatever(1, 2, 3)
};
// this works on any object that implements `operator ()`
wrapped_create_task(f)
同样,非常重要 f
在执行期间保持活动状态。你不能把它放在一个在任务完成之前就死掉的堆栈上。
我正在包装来自 freeRTOS 的 C 函数,它创建一个任务并在 C++ 中使用 void 指针获取其参数。该函数看起来有点像这样:
void createTask(TaskFunction_t taskCode, void * args);
据我所知,要将 2 个参数传递给任务,我需要创建一个结构,将其地址转换为 void*,传递它,然后将其转换回原始状态,如下所示:
struct Params
{
const int a;
const double b;
};
static void task(void * args)
{
auto params = *static_cast<Params*>(args);
// do something with params.a and params.b
}
int main()
{
Params params{1, 2.2};
createTask(task, static_cast<void*>(¶ms));
}
包装此函数的首选方式是什么,以便我可以传递可变类型的可变数量的参数?我应该只留下 void * args 作为参数,还是可以用模板或元组来做一些事情来稍微简化这个过程。
从 C++11 开始,你可以使用类似
的东西static void call_task(void *args) {
auto& f = *static_cast<std::function<void()>*>(args);
f();
}
// note: need this to stay alive!
std::function<void()> f = [&](){
// Any arguments you like here
do_whatever(1, 2, 3)
};
CreateTask(call_task, static_cast<void*>(&f));
您需要确保 f
的生命周期长于任务的生命周期(就像您对 Params
对象所做的那样)。
您实际上可以完全避免 std::function
,因为:
template<typename Func>
void call_func(void *args) {
auto& f = *static_cast<Func*>(args);
f();
}
template<typename Func>
void wrapped_create_task(Func& func) {
CreateTask(call_func<Func>, static_cast<void*>(&func));
}
// you can still use `std::function` here, but you don't have to.
auto f = [&](){
// Any arguments you like here
do_whatever(1, 2, 3)
};
// this works on any object that implements `operator ()`
wrapped_create_task(f)
同样,非常重要 f
在执行期间保持活动状态。你不能把它放在一个在任务完成之前就死掉的堆栈上。