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;
});