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*>(&params));
}

변수 유형의 가변 인수를 전달할 수 있도록이 함수를 래핑하는 선호되는 방법은 무엇입니까? 그냥 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. 작업이 수행되기 전에 죽는 스택에 놓을 수 없습니다.