13

这个 SO线程中,Brian Postow 提出了一个涉及假匿名函数的解决方案:

制作一个 comp(L) 函数,该函数返回长度为 L 的数组的 comp 版本...这样 L 就成为参数,而不是全局

如何实现这样的功能?

4

3 回答 3

6

请参阅我刚刚发布的该问题的答案。您可以使用该callback(3)库在运行时生成新函数。它不符合标准,因为它涉及许多丑陋的特定于平台的黑客攻击,但它确实适用于大量系统。

该库负责分配内存,确保内存是可执行的,并在必要时刷新指令缓存,以确保动态生成的代码(即闭包)是可执行的。它本质上会生成在 x86 上可能看起来像这样的代码存根:

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

然后返回第一条指令的地址。这个存根所做的是将返回地址存储到 ECX(x86 调用约定中的暂存寄存器),将一个额外的参数压入堆栈(指向 thunk 的指针),然后重新压入返回地址。然后,它跳转到实际功能。这会导致函数误以为它有一个额外的参数,即闭包的隐藏上下文。

它实际上比这更复杂(在存根末尾调用的实际函数是__vacall_r,而不是函数本身,并且__vacall_r()处理更多的实现细节),但这是基本原理。

于 2009-10-31T15:51:10.917 回答
2

我不相信你可以用 C99 做到这一点——除非你开始在运行时手动生成机器代码,否则没有可用的部分应用程序或关闭工具。

Apple 最近提出的块会起作用,尽管您需要为此提供编译器支持。这是块的简要概述。 我不知道苹果以外的任何供应商何时/是否会支持它们。

于 2009-10-31T13:59:22.363 回答
1

在 C 或 C++ 的运行时不可能生成普通函数。Brian 的建议是基于一个大的“如果”:“......如果你可以伪造匿名函数......”。“如果”的答案是:不,你不能。(虽然不清楚他所说的“假”是什么意思。)

(在 C++ 中,可以在运行时生成类似函数的对象,但不能生成普通函数。)

以上适用于标准 C 和 C++ 语言。特定的实现可以支持各种实现提供的扩展和/或手动实现的 hack,例如“闭包”、“委托”和类似的东西。当然,这些都与标准 C/C++ 语言无关。

于 2009-10-30T17:03:50.980 回答