有简单的方法吗?
答案 0 :(得分:14)
这是一个非常广泛的问题。从根本上说,闭包是指令指针以及以正确方式执行指令所需的一些存储上下文。你当然可以使用结构和函数指针在C中抛出这样的东西。
假设您表达了一个带有两个整数的闭包,并将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);
还有一个问题:大多数情况下,当你使用闭包时,你想要在创建闭包的代码块的生命周期之外传递上下文。 (例如:您将闭包传递给执行某些异步I / O的函数,并在I / O完成时最终调用闭包)。在这种情况下,您必须确保在堆上分配闭包,并在完成后删除闭包。 (参见底部的完整示例)。
最后要注意的是:这里显然有很多机器,它只适用于一种闭包(一个带两个整数args并返回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;
}
答案 1 :(得分:0)
简单回答:
否强>
很抱歉,除非你将其缩小到某种非常小的闭包功能子集,否则就是这样。
答案 2 :(得分:-1)
我想这取决于你对“简单”的看法。
Scheme的几个实现被设计为集成为C程序的扩展语言。在Scheme中链接,在Scheme中编写你的闭包,你就完成了。