> lambda with capture. [...]
There is a well-known, if perhaps not too widely known, pattern
for doing such things. Suppose we have a function that we would
like to capture-lambda-ize that looks like this:
return-type F( private-data-pointer, ...other arguments... );
In fact let's suppose we have several similar functions, with the
same return type and the same set of "other arguments", but with
different kinds of private data, something like this:
return-type G( G-private-data-pointer, ...other arguments... );
return-type H( H-private-data-pointer, ...other arguments... );
...
To handle these, first we declare a structure type for the
function pointer, and give a typedef for the function type so
things don't get too confusing (disclaimer: none of what looks
like code below has been anywhere near a compiler):
struct FGH_lambda;
typedef return-type FGH_f( struct FGH_lambda *, ..other args.. );
Now define the structure type. It has only one member, a pointer
to function
struct FGH_lambda {
FGH_f *f;
};
Then, for each FGH function we define a struct that will hold the
data for that function. Each of these structs will have as its
first member a struct FGH_lambda. Thus for function F we might
have
struct F_capture_data {
struct FGH_lambda callback[1];
int x;
char *p;
... etc ...
};
Having done this, to create a lambda for F, we create an instance
of its captured data struct:
struct F_capture_data {
{{ F_lambda }},
.x = 3, .p = 0, ...
} closure_1;
To pass this closure to another function, use its 'callback'
member:
function_needing_callback( closure_1.callback );
(Note that 'closure_1.callback' is actually a pointer to the
member, because that member is an array of length 1.)
That function can invoke the callback by using the 'f' member,
and giving the closure as the first argument value:
void
function_needing_callback( struct FGH_lambda *closure ){
closure->f( closure, .. other arguments .. );
}
For the function F_lambda, we have a pointer to the closure data
in the value of the first argument. That pointer needs casting
to get to an appropriate type, but after that one cast everything
is type safe:
return-type
F_lambda( struct FGH_lambda *closure, .. other arguments .. ){
struct F_capture_data *my_data = (void*) closure;
.. now 'my_data' can be used to access the captured data ..
}
Follow the same pattern for functions G and H, etc. If there is
a callback function that doesn't need any private data, it can
use a struct FGH_lambda structure directly, without any enclosing
struct:
struct FGH_lambda simple = { simple_callback_f };
function_needing_callback( &simple );
I may have gone through this outline a bit quickly. Were you
able to follow everything or was there something confusing?
(I hope I didn't make any mistakes in the code. I am keeping
true to my word that the code hasn't been near a compiler. :)