Reputation: 31
I'm using a library written in C. This library accepts callbacks like this:
int(*)(int arg, void* user_param)
Is it possible to create a std::function<int(int, void*)>
and pass it to this library as a callback?
I know that std::function
has a target
method which returns the address of the stored function, but as far as I know it can't return the address if its holding a lambda expression. Or am I wrong?
Upvotes: 1
Views: 1424
Reputation: 41750
You can use lambda functions with C-style function pointers, just not using std::function
.
Lambdas that don't have any capture are convertible to a functions pointer:
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);
}
But there is also a way with lambda with captures, using 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;
});
Upvotes: 2
Reputation: 595557
std::function
cannot be used where a C-style function pointer is expected.
A non-capturing lambda can (but a capturing lambda cannot).
Upvotes: 0
Reputation: 11506
If you want to pass a lambda to the C library, you should be able to, as long as the lambda has no captures. A captureless lambda can be implicitly converted to a function pointer, so simply setting it as a callback should work.
Passing a lambda that uses captures (or e.g. an std::function
) will not work, since they can't be converted to "plain" function pointers, because they hold an internal state.
Upvotes: 0