You must be familiar with some programming language which supports closure mechanism ,don't you?
Unfortunately, C does not support closure like that itself.
You could find out some useful libraries which simulate closure in C if you insisted on closure. But most of those libraries are complex and machine-dependence.
Alternatively, you can change your mind to agree with the C-style closure
if you could change the signature of double ()(unsigned,unsigned);
.
In C, functions itself has no data (or context) except the parameters of it and the static variable which it could access.
So the context must be passed by yourself. Here is a example using extra parameter :
// first, add one extra parameter in the signature of function.
typedef double(function)(double extra, unsigned int,unsigned int);
// second, add one extra parameter in the signature of apply
void apply(double* matrix,unsigned width,unsigned height, function* f, double extra)
{
for (unsigned y=0; y< height; ++y)
for (unsigned x=0; x< width ++x)
matrix[ y*width + x ] = f(x, y, extra);
// apply will passing extra to f
}
// third, in constant_function, we could get the context: double extra, and return it
double constant_function(double value, unsigned x,unsigned y) { return value; }
void test(void)
{
double* matrix = get_a_matrix();
// fourth, passing the extra parameter to apply
apply(matrix, w, h, &constant_function, 1212.0);
// the matrix will be filled with 1212.0
}
Is a double extra
enough? Yes, but only in this case.
How should we do if more context is required?
In C, the general purpose parameter is void*
, we can pass any context though one void* parameter by passing the address of context.
Here is another example :
typedef double (function)(void* context, int, int );
void apply(double* matrix, int width,int height,function* f,void* context)
{
for (int y=0; y< height; ++y)
for (int x=0; x< width ++x)
matrix[ y*width + x ] = f(x, y, context); // passing the context
}
double constant_function(void* context,int x,int y)
{
// this function use an extra double parameter \
// and context points to its address
double* d = context;
return *d;
}
void test(void)
{
double* matrix = get_a_matrix();
double context = 326.0;
// fill matrix with 326.0
apply( matrix, w, h, &constant_function, &context);
}
(function,context) pair
like &constant_function,&context
is the C-style closure
.
Each function(F) that needs a closure must has one context parameter which will be passed to closure as its context.
And the caller of F must use a correct (f,c) pair.
If you can change the signature of function to fit to C-style closure, your code will be simple and machine-independence.
If couldn't (function and apply is not written by you), try to persuade him to change his code.
If failed, you have no choice but to use some closure libraries.