Home > Blockchain >  Converting lambda (cpp) to function pointer (for c)
Converting lambda (cpp) to function pointer (for c)

Time:10-09

I am trying to implement a parallel runtime using argobots api.

In the main.cpp I am using a lambda function which is argument to the "kernel" function in lib.cpp. I need to convert the lambda received in lib.hpp to a function pointer and call "lib_kernel" in lib.c. I have read many answers and came to know that converting lambdas (capture by reference) to function pointer is not possible. Is there any alternative?. I also don't have any idea how deal with the template parameter T in the "kernel" function. Please help.

// main.cpp

#include "lib.hpp"

int main(int argc, char **argv) {
    int result;
    lib::kernel([&]() {
        result = fib(10); 
    }); 
    cout << "Fib(10) = " << result << "\n";
    // fib is parallel implementation of fibonacci
    // similar to passing function pointers to threads
}

// lib.hpp

namespace lib {

    void kernel(T &&lambda) {
        // T is template argument
        // Need to convert lambda to function pointer
        // ie. lib_kernel(fptr, args)
        // Here fptr and args are received from lambda
        // ie. fptr will be fib function 
        // args is value 10.
    }
}

// lib.c

typedef void (*fork_t)(void* args);

void lib_kernel(fork_t fptr, void* args) {
    fptr(args);
}

CodePudding user response:

Pass the address of the capturing lambda into the second parameter (void *). Make a second (non-capturing) lambda to call it:

#include <iostream>

void foo(void (*func)(void *), void *arg)
{
    func(arg);
}

int main()
{
    int var = 42;
    auto lambda = [&]{std::cout << var << '\n';};
    foo([](void *f){(*(decltype(lambda) *)f)();}, &lambda);
}

CodePudding user response:

You can convert a lambda to a function pointer with , i.e.:

typedef void (*func)(void* args);

void kernel(func fn, void* args){ 
    fn(args);
}

void CallKernelWithLambda() {
    func f =  [](void*) { };
    kernel(f, nullptr);
}

However, lambdas that capture cannot be converted to a function pointer -- the following fails to compile:

typedef void (*func)(void* args);

void kernel(func fn, void* args){ 
    fn(args);
}

void CallKernelWithLambda() {
    int value = 0;
    func f =  [&](void*) {   value; };
    kernel(f, nullptr);
}

You need to put the value that you want to capture in static storage or global scope, e.g.:

typedef void (*func)(void* args);

void kernel(func fn, void* args){ 
    fn(args);
}

int value = 0;
void CallKernelWithLambda() {
    func f =  [](void*) {   value; };
    kernel(f, nullptr);
}

Putting the call to kernel inside of a templated function doesn't make any difference, i.e.:

typedef void (*func)(void* args);

void kernel(func fn, void* args){ 
    fn(args);
}

template <typename T>
void CallKernelWithTemplateArgumentLambda(T&& lambda) {
    kernel( lambda, nullptr);
}
int value = 0;
void CallKernelWithLambda() {
    CallKernelWithTemplateArgumentLambda([](void*) {   value; });
}

behaves the same way as the previous snippet.

  • Related