Поддельные анонимные функции в C

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

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

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

Ответы

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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