将 lambda 用于回调函数作为 C 函数参数
Using lambda for callback function as C function parameter
我正在为 pthread_*
函数编写自己的 std::thread
类包装器(出于教育目的)。我提出的构造函数如下所示:
template<class Fn, class... Args>
explicit Thread(Fn&& fn, Args&&... args) {
using Invoker = Thread_invoker<Fn, Args...>;
void* (* start_fn)(void*) = [](void* invoker_ptr) -> void* {
// ...
};
auto invoker = std::make_unique<Invoker>(/* ... */);
const auto err = ::pthread_create(&handle_, nullptr, start_fn, invoker.get());
// ...
invoker.release();
}
我做了一些基本测试,代码有效。但后来我想到,C++函数理论上可以有不同于C函数的调用约定,将start_fn
函数指针传递给pthread_create
可以是UB。 似乎证实了这一点。
进一步挖掘,我发现 this question. Following the spirit of the accepted answer,我将代码更改为:
extern "C" using Thread_start_fn = void* (void*);
Thread_start_fn* start_fn = [](void* invoker_ptr) -> void* {
// ...
};
这个修改是否解决了问题,现在代码合法了吗?
Does this modification solve the problem and is the code legal now?
不,它不能解决问题。您可以从 lambda 表达式中获得的函数指针仅指向 function with C++ language linkage.
确定地获得指向具有C语言链接的函数的指针的方法是使用自由函数。这是您将在流行的标准库实现中看到的方法。例如,in libstdc++
extern "C"
{
static void*
execute_native_thread_routine(void* __p)
{
thread::_State_ptr __t{ static_cast<thread::_State*>(__p) };
__t->_M_run();
return nullptr;
}
// ...
}
我正在为 pthread_*
函数编写自己的 std::thread
类包装器(出于教育目的)。我提出的构造函数如下所示:
template<class Fn, class... Args>
explicit Thread(Fn&& fn, Args&&... args) {
using Invoker = Thread_invoker<Fn, Args...>;
void* (* start_fn)(void*) = [](void* invoker_ptr) -> void* {
// ...
};
auto invoker = std::make_unique<Invoker>(/* ... */);
const auto err = ::pthread_create(&handle_, nullptr, start_fn, invoker.get());
// ...
invoker.release();
}
我做了一些基本测试,代码有效。但后来我想到,C++函数理论上可以有不同于C函数的调用约定,将start_fn
函数指针传递给pthread_create
可以是UB。
进一步挖掘,我发现 this question. Following the spirit of the accepted answer,我将代码更改为:
extern "C" using Thread_start_fn = void* (void*);
Thread_start_fn* start_fn = [](void* invoker_ptr) -> void* {
// ...
};
这个修改是否解决了问题,现在代码合法了吗?
Does this modification solve the problem and is the code legal now?
不,它不能解决问题。您可以从 lambda 表达式中获得的函数指针仅指向 function with C++ language linkage.
确定地获得指向具有C语言链接的函数的指针的方法是使用自由函数。这是您将在流行的标准库实现中看到的方法。例如,in libstdc++
extern "C"
{
static void*
execute_native_thread_routine(void* __p)
{
thread::_State_ptr __t{ static_cast<thread::_State*>(__p) };
__t->_M_run();
return nullptr;
}
// ...
}