C ++에서 void *로 인수를받는 C 함수 감싸기 [중복]
Aug 21 2020
작업을 만들고 C ++에서 void 포인터로 인수를 취하는 freeRTOS의 C 함수를 래핑하고 있습니다. 함수는 다음과 같이 보입니다.
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를 인자로 남겨 두어야할까요? 아니면이 과정을 약간 단순화하기 위해 템플릿이나 튜플으로 할 수있는 일이 있습니까?
답변
2 Eric Aug 21 2020 at 06:54
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
. 작업이 수행되기 전에 죽는 스택에 놓을 수 없습니다.