你必须熟悉一些支持闭包机制的编程语言,不是吗?
不幸的是,C 本身不支持这样的闭包。
如果你坚持使用闭包,你可以找到一些有用的库来模拟 C 中的闭包。但是这些库中的大多数都很复杂并且依赖于机器。
或者,如果您可以更改double ()(unsigned,unsigned); 的签名,您可以改变主意同意C-style closure。
在 C 中,函数本身没有数据(或上下文),除了它的参数和它可以访问的静态变量。
所以上下文必须自己传递。这是一个使用额外参数的示例:
// 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
}
double extra 足够了吗?是的,但仅限于这种情况。
如果需要更多上下文,我们应该怎么做?
在 C 中,通用参数是void*,我们可以通过一个 void* 参数通过传递上下文的地址来传递任何上下文。
这是另一个例子:
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 就是C-style closure。
每个需要闭包的函数(F)都必须有一个上下文参数,该参数将作为其上下文传递给闭包。
并且 F 的调用者必须使用正确的 (f,c) 对。
如果您可以更改函数的签名以适应 C 风格的闭包,您的代码将变得简单且与机器无关。
如果不能(function 和 apply 不是你写的),试着说服他改变他的代码。
如果失败了,你别无选择,只能使用一些闭包库。