4

I can't even type example code... pretty lost. Here's my original function which is NOT a lambda function (I want it to be lambda).

static void* DoublePointer(void** arg, int arg_sz) {
    double* n1 = In(arg[0]);
    double* n2 = In(arg[1]);
    double* n3 = In(arg[arg_sz-1]);

    *n3 = *n1 + *n2;

    return n3;
}

void* func_ptr = DoublePointr; //works fine

But what I really want is this:

my_class.save_the_func = [](void** arg, int arg_sz) {
    double* n1 = In(arg[0]);
    double* n2 = In(arg[1]);
    double* n3 = In(arg[arg_sz-1]);

    *n3 = *n1 + *n2;

    return n3;
}

my_class.point_to_func = save_the_func // point_to_func is the void* member

What do you have to do to finally get a void* pointing to the lambda function? Like I said, a non-lambda function works just fine.

The reason I want it this way is because eventually I want my code to look like this:

std::vector<function_entry> MyFuncEntry ={
add_function("MRP_DoublePointer2", "double", "double,double", "n1,n2", "add two numbers",
    [](void** arg, int arg_sz)->void* {
    double* n1 = In(arg[0]);
    double* n2 = In(arg[1]);
    double* n3 = In(arg[arg_sz-1]);

    *n3 = *n1 + *n2;

    return n3;
}),

add_function("MRP_DoublePointer3", "double", "double,double", "n1,n2", "add two numbers",
    [](void** arg, int arg_sz)->void* {
    double* n1 = In(arg[0]);
    double* n2 = In(arg[1]);
    double* n3 = In(arg[arg_sz-1]);

    *n3 = *n1 + *n2;

    return n3;
})

};

In other words, I want to define a function and some other needed parameters in the same place. Add_function returns a function_entry class that holds some strings plus the lambda function, basically I'm trying to define those strings next to the function so it's easier to maintain, it's not in two different places.

If this is bad / computationally expensive then I guess I should stick with non-lambda.

Here's the error I'm getting: lambda error

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
Elan Hickler
  • 1,099
  • 1
  • 11
  • 28
  • 1
    Why using `void*` everywhere ? – Jarod42 Dec 16 '15 at 01:46
  • I have no choice, I'm interfacing with another software's API that takes void*, oh and the arguments MUST be void** and int. – Elan Hickler Dec 16 '15 at 01:46
  • 3
    Since the lambda is non-capturing, you should be able to add a unary `+` in front of the lambda to force it to decay to an ordinary function pointer. More info here: http://stackoverflow.com/q/18889028/1553090 – paddy Dec 16 '15 at 01:51
  • IIRC, lambda functions produce hidden classes with a public `operator()`, and return references to objects of those hidden classes. So you cannot make a pointer receive a reference an object. – Paulo1205 Dec 16 '15 at 01:55
  • Not sure that it expected that `void* (*)(void**, int)` is converted to `void*` btw. – Jarod42 Dec 16 '15 at 01:55
  • `void* func_ptr = DoublePointr; //works fine` No, it does not. [Not in C++.](http://ideone.com/qRRY85) That might fly in C, but you're using C++. So it's rather unclear what you're asking for. – Nicol Bolas Dec 16 '15 at 02:54
  • @ElanHickler: Your answer is [over here](http://stackoverflow.com/questions/20525977/how-can-i-pass-a-c-lambda-to-a-c-callback-that-expects-a-function-pointer-and). – Nicol Bolas Dec 16 '15 at 02:57

3 Answers3

1

The issue with getting a void* pointer to a lambda expression is that the result of a lambda expression is an actual honest-to-goodness object, not a pointer to an object. Just as you can't assign a std::vector or a std::string to a void*, you can't assign the result of a lambda expression to a void*.

Interestingly, the initial code you wrote - assigning a function pointer to a void* - isn't actually guaranteed to compile! The C++ standard makes a distinction between function pointers and object pointers, and it's not portable to cast between the two of them. In fact, some compilers would outright reject your code.

If you need to store a pointer to an arbitrary function type, consider using std::function, which is type-safe and more clearly indicates what you're trying to do.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • I would gladly use std::function, I was trying to cast that to `void*`, I just don't know how! :( I know how to make the std::function: `std::function func_member = [](){} etc` but after that I'm lost. – Elan Hickler Dec 16 '15 at 02:27
  • You should then be able to call `func_member` as if it were a normal function: `void* result = func_member(args, arg_sz);` – templatetypedef Dec 16 '15 at 02:28
1

What you're trying to do will only work in certain circumstances; see warning at end. Lambdas are not functions, and you can't get a function pointer address for them. What you can do, however, is to create both a function and a lambda that work together.

std::function f;
void call_f()
{
    f();
}

Just assign to f and pass the address of call_f to your API.

BIG WARNING: This isn't even remotely thread safe as written. Protect it as any other single-use-at-a-time resource if you need this in a multiprocessing context. If just one is too much of a hotspot, you can make a fixed-size pool of functions, but that's significantly more complicated.

eh9
  • 7,340
  • 20
  • 43
0

declare a typename for a C-style labmda function in the format

return_type ( * ) ( params )

in our case, it would be this:

using my_lambda_type = void*(*)(void**, int)

now we declare:

my_lambda_type my_func = [](void** args, int arg_sz)->void* { /*do stuff*/ }

You can omit the ->void* to automatically deduce the return type.

finally:

void* my_func_pointer = my_func;

bonus, here's how to define c-style lambda as a function parameter input

void func_with_func_parameter(void*(*par_name_goes_here)(void**, int)) 
{
    //do stuff
}

the same as:

void func_with_func_parameter(my_lambda_type param_name_goes_here) 
{
    //do stuff
}
Elan Hickler
  • 1,099
  • 1
  • 11
  • 28