在C语言中动态创建函数

在C语言中动态创建函数,c,dynamic,C,Dynamic,如何在C中动态创建函数 我尝试将我的C问题总结如下: 我有一个矩阵,我希望能够使用一些函数来生成它的元素 函数没有参数 因此,我定义如下: typedef double(function)(unsigned int,unsigned int); /* writes f(x,y) to each element x,y of the matrix*/ void apply(double ** matrix, function * f); 现在我需要在代码中生成常量函数。我曾想过创建一个嵌套

如何在C中动态创建函数

我尝试将我的C问题总结如下:

  • 我有一个矩阵,我希望能够使用一些函数来生成它的元素

  • 函数没有参数

因此,我定义如下:

typedef double(function)(unsigned int,unsigned int);

/* writes f(x,y) to each element x,y of the matrix*/
void apply(double ** matrix, function * f);
现在我需要在代码中生成常量函数。我曾想过创建一个嵌套函数并返回其指针,但GCC手册(允许嵌套函数)说:

“如果您试图通过嵌套函数在 包含函数已退出,所有地狱都将崩溃。“

我希望从这段代码中

function * createConstantFunction(const double value){
 double function(unsigned int,unsigned int){
   return value;
 }
 return &function;
}
那么我怎样才能让它工作呢


谢谢

如果您想动态编写代码以执行,这可能是一个好方法


在上面的代码中,您试图创建一个闭包。C不支持这一点。有一些令人发指的方法可以伪造它,但是开箱即用,您无法在运行时将变量绑定到函数中。

C是一种编译语言。不能在运行时“用C”创建代码;没有特定的C支持将指令发送到内存等。当然,您可以尝试分配内存,确保它是可执行的,并在那里发出原始机器代码。然后使用合适的函数指针从C调用它


不过,您不会从语言本身获得任何帮助,这就像在旧的8位机器上生成代码并在BASIC中调用代码一样。

一种方法是使用所需的函数集编写一个标准C文件,通过gcc编译并将其加载为动态库,以获取指向函数的指针

归根结底,如果您能够指定函数而不必动态定义它们,可能会更好(比如通过使用通用模板函数来获取定义其特定行为的参数)。

如前所述,该语言不支持“在运行时创建代码”,这将需要大量工作

我自己没用过,但我的一个同事发誓说Lua是一种“嵌入式语言”。至少从理论上讲,有一种方法允许您执行动态(脚本化)操作

当然,缺点是最终用户可能需要一些Lua方面的培训


这可能是一个愚蠢的问题,但为什么必须在应用程序中生成函数呢?类似地,最终用户自己生成函数(而不是从您提供的一个或多个预定义函数中进行选择)有什么好处?这种机制称为反射,其中代码在运行时修改自己的行为。Java支持执行此任务。
但我认为这种支持在C语言中是不可用的

Sun网站上说:

反射是强大的,但不应该如此 不加区别地使用。如果是 可以执行操作 如果不使用反射,那么它就是 最好避免使用它。这个 应保持以下关注事项: 当通过 反思

反思的弊端

性能开销因为 反射涉及以下类型: 动态解析的特定Java 无法进行虚拟机优化 将被执行。因此,反思 操作的性能较慢 而不是他们的不反思 对应,并且应避免使用 称为 经常对性能敏感 应用程序

安全限制

反射需要运行时 可能不存在的权限 在安全管理器下运行时。 这是一个重要的考虑因素 对于必须在 受限安全上下文,例如 在小程序中

内部构件的暴露

因为反射允许代码 执行可能需要的操作 在非反射代码中是非法的,例如 作为访问私有字段和 方法,可以使用反射 导致意外的副作用, 这可能导致代码功能失调 并且可能会破坏可移植性。 反射代码打破了抽象 因此可能会随着时间的推移而改变行为 平台升级


看起来您来自另一种语言,您通常使用这种类型的代码。C不支持它,尽管您当然可以编写一些东西来动态生成代码,但这很可能是不值得的


相反,您需要做的是在函数中添加一个额外的参数,该函数引用它应该处理的矩阵。这很可能是支持动态函数的语言在内部所做的。

如果您确实需要动态创建函数,也许嵌入式C解释器可以提供帮助。我刚在谷歌上搜索了“嵌入式C解释器”,结果得到了Ch:

从未听说过,所以我对它一无所知,但它似乎值得一看。

使用,它处理特定于平台的诡计,以实现此目的:

#include <stdio.h>
#include <stdarg.h>
#include <callback.h>

static double internalDoubleFunction(const double value, ...) {
    return value;
}
double (*constDoubleFunction(const double value))() {
    return alloc_callback(&internalDoubleFunction, value);
}

main() {
    double (*fn)(unsigned int, unsigned int) = constDoubleFunction(5.0);
    printf("%g\n", (*fn)(3, 4));
    free_callback(fn);
    return 0;
}
#包括
#包括
#包括
静态双内部双函数(常量双值,…){
返回值;
}
double(*constDoubleFunction(constdoublevalue))(){
返回alloc_回调(&internalDoubleFunction,value);
}
main(){
double(*fn)(无符号整数,无符号整数)=constDoubleFunction(5.0);
printf(“%g\n”,(*fn)(3,4));
免费回拨(fn);
返回0;
}

(未经测试,因为我目前没有安装FFCALL,但我记得它是这样工作的。)

您必须熟悉一些支持闭包机制的编程语言,不是吗? 不幸的是,C本身不支持这样的闭包

您可以找到一些有用的库来模拟
// first, add one extra parameter in the signature of function.
typedef double(function)(double extra, unsigned int,unsigned int);

// second, add one extra parameter in the signature of apply
void apply(double* matrix,unsigned width,unsigned height, function* f, double extra)
{
        for (unsigned y=0; y< height; ++y)
            for (unsigned x=0; x< width ++x)
                    matrix[ y*width + x ] = f(x, y, extra);
        // apply will passing extra to f
}

// third, in constant_function, we could get the context: double extra, and return it
double constant_function(double value, unsigned x,unsigned y) { return value; }

void test(void)
{
        double* matrix = get_a_matrix();
        // fourth, passing the extra parameter to apply
        apply(matrix, w, h, &constant_function, 1212.0);
        // the matrix will be filled with 1212.0
}
typedef double (function)(void* context, int, int );
void apply(double* matrix, int width,int height,function* f,void* context)
{
        for (int y=0; y< height; ++y)
            for (int x=0; x< width ++x)
                    matrix[ y*width + x ] = f(x, y, context); // passing the context
}
double constant_function(void* context,int x,int y)
{
        // this function use an extra double parameter \
        //    and context points to its address
        double* d = context;
        return *d;
}
void test(void)
{
        double* matrix = get_a_matrix();
        double context = 326.0;
        // fill matrix with 326.0
        apply( matrix, w, h, &constant_function, &context);
}