用并集和函数指针在C中实现函数委托

用并集和函数指针在C中实现函数委托,c,delegates,function-pointers,anonymous-function,unions,C,Delegates,Function Pointers,Anonymous Function,Unions,我希望能够将函数一般地传递给C语言中的函数。我已经使用C语言好几年了,我知道实现正确闭包和高阶函数的障碍。这几乎是无法克服的 我仔细调查了StackOverflow,看看其他消息来源对此有何评论: …除了使用varargs或assembly之外,没有一个通用答案是银弹。我没有汇编的骨骼,但是如果我能在宿主语言中有效地实现一个特性,我通常会尝试 因为我不能轻易得到霍夫。。。 我喜欢高阶函数,但在紧要关头我会接受委托。我怀疑通过下面的代码,我可以在C中得到一个可行的委托实现 我想

我希望能够将函数一般地传递给C语言中的函数。我已经使用C语言好几年了,我知道实现正确闭包和高阶函数的障碍。这几乎是无法克服的

我仔细调查了StackOverflow,看看其他消息来源对此有何评论:

…除了使用varargs或assembly之外,没有一个通用答案是银弹。我没有汇编的骨骼,但是如果我能在宿主语言中有效地实现一个特性,我通常会尝试

因为我不能轻易得到霍夫。。。 我喜欢高阶函数,但在紧要关头我会接受委托。我怀疑通过下面的代码,我可以在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]);
        }
    }
}
void映射(struct-fun-f,int-arr[20]){
int i=0;
如果(f.fun\u type==INT\u fun){
对于(;i<20;i++){
arr[i]=f.function.int_-fun(arr[i]);
}
}
}

不幸的是,这种方法对学员来说有一些明显的缺点:

  • 无类型检查,通过检查“乐趣类型”字段保存您自己进行的检查

  • 类型检查在代码中引入了额外的条件,使代码比以前更加混乱和分支
  • 函数的(安全)可能排列的数量受“fun_type”变量的大小限制
  • 枚举和函数指针定义列表必须由计算机生成。除此之外,其他任何事情都近乎疯狂
  • 遗憾的是,使用普通的C并不像mov->调用序列那样高效,这可能是在汇编中完成的(有些困难)

有没有人知道更好的方法来完成C语言中的委托? 注意:越便携、越高效越好


<强>也请注意:我听说过C++。但是,我对C++解决方案不感兴趣——只是c.< /p> < p>您可以向所有函数添加<代码>空隙*/COD>参数,以允许绑定参数、委托等。不幸的是,您需要为处理外部函数和函数指针的任何内容编写包装器。

有两个问题,我研究了提供基本技术稍有不同版本的类似技术。这样做的缺点是会丢失编译时检查,因为参数列表是在运行时生成的

第一个是。这种方法使用代理函数来调用函数指针和函数的参数

第二个是

基本思想是拥有一个内存区域,然后用于构建参数列表,然后将该内存区域作为函数调用的一部分推送到堆栈上。结果是被调用函数将内存区域视为参数列表

在C语言中,关键是定义一个
struct
,它包含一个数组,然后用作内存区域。调用被调用函数时,整个
struct
通过值传递,这意味着数组中设置的参数随后被推送到堆栈上,以便被调用函数看到的不是
struct
值,而是参数列表

对于curry问题的答案,内存区域包含一个函数指针以及一个或多个参数,这是一种闭包。然后将内存区域交给代理函数,代理函数实际使用闭包中的参数调用该函数


这是因为标准C函数调用将参数推送到堆栈上,调用函数,当函数返回时,调用方会清理堆栈,因为它知道实际推送到堆栈上的是什么。

“类型检查会在代码中引入额外的条件,使代码比以前更混乱、更分支。”这就是为什么函数指针类型的并集没有多大意义的原因,因为您已经有了enum,您可以简单地将其传递给switch语句,然后switch语句调用相应的函数。此外,您似乎没有考虑到参数和返回值与所有这些匹配的位置。最后,作为一个通用的编程经验法则:泛型编程总是让代码变慢。至于参数,在C中最可能的通用解决方法是使用另一个可能类型的并集。是的,这就像罪恶一样丑陋。当我查看为发布的方法生成的程序集输出时,我发现它的效率远远低于我希望的效率。这就是为什么我要征求更好的方法的建议。@PhilipConrad:嗨,你有没有尝试过创建一个大型的由机器生成的函数类型列表?这是过去3个月来唯一的答案,出于对海报的礼貌,我将其标记为答案。这听起来是个不错的方法,我唯一保留的是按值复制大型结构。我知道这“更安全”,但会有一些严重的管理费用,对吗?@PhilipConrad始终存在管理费用的问题,以及管理费用的成本是否由该功能提供的实用程序所涵盖。需要进行价值分析,以确定不使用功能的成本与使用功能的成本。另一个考虑因素是使用功能的环境。如果应用程序的大部分时间都在等待用户输入,我不确定几毫秒是否会产生这么大的差异。