std::function 到 C 风格的函数指针
std::function to C-style function pointer
我正在使用用 C 编写的库。该库接受这样的回调:
int(*)(int arg, void* user_param)
是否可以创建一个 std::function<int(int, void*)>
并将其作为回调传递给该库?
我知道 std::function
有一个 target
方法,它 return 是存储函数的地址,但据我所知它不能 return地址,如果它持有 lambda 表达式。还是我错了?
如果你想将 lambda 传递给 C 库,你应该可以,只要 lambda 没有捕获。无捕获 lambda 可以隐式转换为函数指针,因此只需将其设置为回调即可。
传递使用捕获(或例如 std::function
)的 lambda 将不起作用,因为它们不能转换为“普通”函数指针,因为它们保持内部状态。
std::function
不能用于需要 C-style 函数指针的地方。
A non-capturing lambda 可以(但 capturing lambda 不能)。
您可以使用带有 C-style 函数指针的 lambda 函数,只是不使用 std::function
.
没有任何捕获的 Lambda 可转换为函数指针:
using callback_t = int(*)(int arg, void* user_param);
void set_c_callback(callback_t, void* user_param);
// ...
void foo() {
set_c_callback([](int a, void* data) {
// code
}, nullptr);
}
但也有一种使用 lambda 捕获的方法,使用 std::any
:
// The storage can be inside a class instead of a global
std::any lambda_storage;
template<typename T>
void foo(T lambda) {
lambda_storage = lambda;
set_c_callback([](int n, void* user_data) {
auto& lambda = *std::any_cast<T>(static_cast<std::any*>(user_data));
lambda(n);
}, &lambda_storage)
}
// ...
foo([k = 1](int n) {
std::cout << n + k << std::endl;
});
我正在使用用 C 编写的库。该库接受这样的回调:
int(*)(int arg, void* user_param)
是否可以创建一个 std::function<int(int, void*)>
并将其作为回调传递给该库?
我知道 std::function
有一个 target
方法,它 return 是存储函数的地址,但据我所知它不能 return地址,如果它持有 lambda 表达式。还是我错了?
如果你想将 lambda 传递给 C 库,你应该可以,只要 lambda 没有捕获。无捕获 lambda 可以隐式转换为函数指针,因此只需将其设置为回调即可。
传递使用捕获(或例如 std::function
)的 lambda 将不起作用,因为它们不能转换为“普通”函数指针,因为它们保持内部状态。
std::function
不能用于需要 C-style 函数指针的地方。
A non-capturing lambda 可以(但 capturing lambda 不能)。
您可以使用带有 C-style 函数指针的 lambda 函数,只是不使用 std::function
.
没有任何捕获的 Lambda 可转换为函数指针:
using callback_t = int(*)(int arg, void* user_param);
void set_c_callback(callback_t, void* user_param);
// ...
void foo() {
set_c_callback([](int a, void* data) {
// code
}, nullptr);
}
但也有一种使用 lambda 捕获的方法,使用 std::any
:
// The storage can be inside a class instead of a global
std::any lambda_storage;
template<typename T>
void foo(T lambda) {
lambda_storage = lambda;
set_c_callback([](int n, void* user_data) {
auto& lambda = *std::any_cast<T>(static_cast<std::any*>(user_data));
lambda(n);
}, &lambda_storage)
}
// ...
foo([k = 1](int n) {
std::cout << n + k << std::endl;
});