Вы должны быть знакомы с некоторым языком программирования, который поддерживает механизм закрытия, не так ли?
К сожалению, C не поддерживает закрытие как таковое.
Вы можете найти несколько полезных библиотек, которые имитируют закрытие в C, если вы настаивали на закрытии. Но большинство этих библиотек сложны и зависят от машины.
Кроме того, вы можете передумать согласиться с C-style closure
, если вы можете изменить подпись double ()(unsigned,unsigned);
.
В 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
как &constant_function,&context
это C-style closure
.
Каждая функция (F), которая нуждается в закрытии, должна иметь один параметр контекста, который будет передан закрытию в качестве контекста.
И вызывающий F должен использовать правильную (f, c) пару.
Если вы можете изменить сигнатуру функции, чтобы она соответствовала замыканию в стиле C, ваш код будет простым и независимым от машины.
Если не смог (функция и применение не написаны вами), попробуйте убедить его изменить свой код.
В случае неудачи у вас нет другого выбора, кроме как использовать некоторые библиотеки закрытия.