Как эмулировать закрытия в c

Существует ли простой путь?

7
задан Pierreten 20 March 2010 в 00:51
поделиться

3 ответа

Это довольно широкий вопрос. По сути, замыкание - это указатель инструкции вместе с некоторым сохраненным контекстом, который необходим для правильного выполнения инструкций. Конечно, вы можете создать что-то подобное вместе в C, используя структуры и указатели на функции.

Допустим, вы выражаете замыкание, которое принимает два int и возвращает void как структуру:

typedef struct VoidClosureIntInt {
  void (*fn)(int, int);
  int first;
  int second;
} VoidClosureIntInt;

и предположим, что у вас есть функция:

void Foo(int x, int y);

Теперь, чтобы создать замыкание, которое будет вызывать Foo (23, 42), вы сделал бы:

VoidClosureIntInt closure = {&Foo, 23, 42};

А затем, чтобы позже выполнить это закрытие, вы бы сделали:

(*closure.fn)(closure.first, closure.second);

Еще одна загвоздка: большую часть времени, когда вы используете замыкания, вы хотите передавать контекст за пределы времени жизни блока кода в который вы создаете закрытие. (Пример: вы передаете закрытие функции, которая выполняет некоторый асинхронный ввод-вывод и в конечном итоге вызовет ваше закрытие, когда этот ввод-вывод будет завершен). В таких случаях вы должны обязательно разместить закрытие в куче и удалить закрытие, когда закончите с ним. (См. Полный пример внизу).

И последнее замечание: здесь явно много механизмов, и это только для одного вида замыкания (функция, которая принимает два целых аргумента и возвращает void).Когда я видел, как это делается на C, это часто делается генератором кода, который создает механизмы для множества различных типов замыканий. Вы также можете уменьшить количество шаблонов, поддерживая только замыкания, которые принимают некоторые (фиксированное количество) аргументов void *, а затем приведение типов в функции, которые вы используете для реализации этих замыканий.

Если вы работаете на C ++, вы можете воспользоваться преимуществами языковых функций, чтобы сделать это гораздо более обобщенно и с гораздо меньшим набором текста. См. Пример Boost.Function .

Полный пример:

#include <stdio.h>
#include <stdlib.h>

// Closure support.

typedef struct VoidClosureIntInt {
  void (*fn)(int, int);
  int first;
  int second;
} VoidClosureIntInt;

// The returned closure should be run via RunAndDeleteClosure().
VoidClosureIntInt* NewClosure(void (*fn)(int, int), int first, int second) {
  VoidClosureIntInt* closure = malloc(sizeof(*closure));
  closure->fn = fn;
  closure->first = first;
  closure->second = second;
  return closure;
}

void RunAndDeleteClosure(VoidClosureIntInt* closure) {
  (*closure->fn)(closure->first, closure->second);
  free(closure);
}


// Example use.

void Foo(int x, int y) {
  printf("x=%d\ny=%d\n", x, y);
}

// We take memory ownership of closure.
void SomeAsynchronousFunction(VoidClosureIntInt* closure) {
  RunAndDeleteClosure(closure);
}

int main(int argc, char** argv) {
  VoidClosureIntInt* closure = NewClosure(&Foo, 23, 42);
  SomeAsynchronousFunction(closure);
  return 0;
}
14
ответ дан 6 December 2019 в 21:12
поделиться

Простой ответ:

НЕТ

Извините, если вы не сузите это до какого-то очень небольшого подмножества функций замыканий, так оно и есть.

-1
ответ дан 6 December 2019 в 21:12
поделиться

Думаю, это зависит от того, каково ваше представление о "простоте".

Есть несколько реализаций Scheme, которые предназначены для интеграции в качестве языка расширения для программ на C. Подключите Scheme, напишите ваше закрытие на Scheme, и готово.

-1
ответ дан 6 December 2019 в 21:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: