我希望能够将一个函数通常传递给C中的函数。我已经使用了C几年了,我知道实现正确闭包的障碍和更高阶的函数。这几乎是不可逾越的。
我搜索了StackOverflow以了解其他消息来源对此事的看法:
......除了使用varargs或汇编之外,没有人有一个银弹通用答案。我没有装配的骨头,但如果我能用主语言有效地实现一个功能,我通常会尝试。
我喜欢更高阶的功能,但是我会满足于代表们。我怀疑使用下面的代码,我可以在C中获得可行的委托实现。
想到这样的实现:
enum FUN_TYPES {
GENERIC,
VOID_FUN,
INT_FUN,
UINT32_FUN,
FLOAT_FUN,
};
typedef struct delegate {
uint32 fun_type;
union function {
int (*int_fun)(int);
uint32 (*uint_fun)(uint);
float (*float_fun)(float);
/* ... etc. until all basic types/structs in the
program are accounted for. */
} function;
} delegate;
用法示例:
void mapint(struct fun f, int arr[20]) {
int i = 0;
if(f.fun_type == INT_FUN) {
for(; i < 20; i++) {
arr[i] = f.function.int_fun(arr[i]);
}
}
}
不幸的是,这种方法对代表有一些明显的缺点:
注意:越便携,越高效越好
另外,注意:我听说过Don Clugston's very fast delegates用于C ++。但是,我对C ++解决方案不感兴趣 - 只是C。
答案 0 :(得分:2)
您可以为所有函数添加void*
参数,以允许绑定参数,委托等。不幸的是,你需要为处理外部函数和函数指针的任何东西编写包装器。
答案 1 :(得分:0)
我有两个问题,我研究了类似的技术,提供了基本技术略有不同的版本。这样做的缺点是你会丢失编译时检查,因为参数列表是在运行时构建的。
第一个是my answer to the question of Is there a way to do currying in C。此方法使用代理函数来调用函数指针和函数的参数。
基本思想是有一个存储区,然后用于构建参数列表,然后将该存储区作为调用函数的一部分压入堆栈。结果是被调用函数将内存区域视为参数列表。
在C中,关键是定义一个struct
,其中包含一个数组,然后将其用作存储区。当调用被调用函数时,整个struct
将通过值传递,这意味着设置到数组中的参数然后被推送到堆栈,以便被调用函数看不到struct
值,而是参数列表。
对于咖喱问题的答案,内存区域包含一个函数指针以及一个或多个参数,一种闭包。然后将内存区域传递给代理函数,该代理函数实际上使用闭包中的参数调用函数。
这是有效的,因为标准的C函数调用将参数压入堆栈,调用函数,当函数返回时,调用者清理堆栈,因为它知道实际上是什么被压入堆栈。