Поддельные анонимные функции в C - PullRequest
13 голосов
/ 30 октября 2009

В этот SO поток, Брайан Постов предложил решение, включающее фальшивые анонимные функции:

сделать функцию comp (L), которая возвращает версию comp для массивов длины L ... таким образом, L становится параметром, а не глобальным

Как мне реализовать такую ​​функцию?

Ответы [ 3 ]

6 голосов
/ 31 октября 2009

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

Библиотека заботится о выделении памяти, проверяя, является ли память исполняемой, и, при необходимости, очищая кэш команд, чтобы гарантировать, что динамически генерируемый код (т. Е. Замыкание) является исполняемым. По сути, он генерирует заглушки кода, которые могут выглядеть следующим образом на x86:

  pop %ecx
  push $THUNK
  push %ecx
  jmp $function
THUNK:
  .long $parameter

А затем возвращает адрес первой инструкции. Эта заглушка сохраняет адрес возврата в ECX (пустой регистр в соглашении о вызовах x86), помещает дополнительный параметр в стек (указатель на thunk), а затем повторно отправляет адрес возврата. Затем он переходит к фактической функции. Это приводит к тому, что функция обманывается, думая, что у нее есть дополнительный параметр, который является скрытым контекстом замыкания.

На самом деле все сложнее (фактическая функция, вызываемая в конце заглушки, __vacall_r, а не сама функция, а __vacall_r() обрабатывает больше деталей реализации), но это основной принцип.

2 голосов
/ 31 октября 2009

Я не верю, что вы можете сделать это с C99 - нет частичного приложения или средства закрытия, если вы не начнете вручную генерировать машинный код во время выполнения.

Недавно предложенные блоки Apple будут работать, хотя для этого вам нужна поддержка компилятора. Вот краткий обзор блоков. Я понятия не имею, когда / если какой-либо поставщик вне Apple будет их поддерживать.

1 голос
/ 30 октября 2009

Невозможно генерировать обычные функции во время выполнения ни в C, ни в C ++. То, что предложил Брайан, основано на большом «если»: «... если вы можете подделать анонимные функции ...». И ответ на это «если»: нет, вы не можете. (Хотя не ясно, что он имел в виду под «подделкой».)

(В C ++ можно генерировать функциональные объекты во время выполнения, но не обычные функции.)

Вышесказанное относится к стандартным языкам C и C ++. Конкретные реализации могут поддерживать различные предоставляемые реализацией расширения и / или реализованные вручную хаки, такие как «замыкания», «делегаты» и подобные вещи. Разумеется, это никак не связано со стандартными языками Си / Си ++.

...