1

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?

1
  • Lambdas with captures cannot be cast to function types. Commented Oct 29, 2020 at 17:23

3 Answers 3

2

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;
});
Sign up to request clarification or add additional context in comments.

4 Comments

That 2nd lambda still doesn't use captures. It's the equivalent of a free function using a global variable.
@Darhuuk yes. But you can have that std::any in the storage of a class.
That way it's not a global, it is simply attached to the class instance.
True, that's a nice way to add a layer of indirection around the capture.
0

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.

Comments

0

std::function cannot be used where a C-style function pointer is expected.

A non-capturing lambda can (but a capturing lambda cannot).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.