【问题标题】:Fake anonymous functions in CC中的假匿名函数
【发布时间】:2009-10-30 15:09:45
【问题描述】:

this SO线程中,Brian Postowsuggested涉及假匿名函数的解决方案:

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

如何实现这样的功能?

【问题讨论】:

  • 我认为没有必要在您的问题中提供指向 stackoverflow.com 主页的链接。
  • 您链接到的问题是关于如何在 C++ 中执行此操作。此问题标记为 C。您想了解哪个?
  • Barry 提供的解决方案是用 C 语言编写的。大多数 cmets 建议用 C++ 解决我的第一个问题是不可能的。
  • 我真的很想看看是否有人可以在符合标准的 C 中想出一个好方法来做到这一点。
  • 好吧,既然布赖恩也在谈论将数组复制到向量中并再次返回(建议每次复制需要 2ns 或大约 3 个时钟周期),我不相信他是认真的并且知道他在说什么。我不知道在 C 中实现闭包的任何方法。您可以通过依赖全局或线程本地数据来“作弊”,但是调用约定和函数指针的性质使得对同一函数的两个不同调用不可能“看到” L 的不同值,除非 (a) 它已更改,或 (b) 调用是在不同的上下文中进行的。

标签: c anonymous-function


【解决方案1】:

有关该问题,请参见 the answer I just posted。您可以使用callback(3) 库在运行时生成新函数。它不符合标准,因为它涉及许多丑陋的特定于平台的 hack,但它确实适用于大量系统。

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

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

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

其实比那个复杂(stub末尾调用的实际函数是__vacall_r,而不是函数本身,__vacall_r()处理更多的实现细节),但这是基本原理。

【讨论】:

    【解决方案2】:

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

    Apple 最近提出的块可以工作,但您需要为此提供编译器支持。 Here's a brief overview of blocks.我不知道苹果以外的任何供应商何时/是否会支持它们。

    【讨论】:

    • clang 编译器支持 Blocks,显然是因为 Apple 资助了该项目。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多