Dynamically creating functions in C

前端 未结 10 1684
-上瘾入骨i
-上瘾入骨i 2020-12-09 10:52

How can I dynamically create a function in C?

I try to summarize my C problem as follows:

  • I have a matrix and I want to be able to use some function

10条回答
  •  被撕碎了的回忆
    2020-12-09 11:14

    You must be familiar with some programming language which supports closure mechanism ,don't you? Unfortunately, C does not support closure like that itself.

    You could find out some useful libraries which simulate closure in C if you insisted on closure. But most of those libraries are complex and machine-dependence.
    Alternatively, you can change your mind to agree with the C-style closure if you could change the signature of double ()(unsigned,unsigned);.

    In C, functions itself has no data (or context) except the parameters of it and the static variable which it could access.
    So the context must be passed by yourself. Here is a example using extra parameter :

    // 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
    }
    

    Is a double extra enough? Yes, but only in this case.
    How should we do if more context is required?
    In C, the general purpose parameter is void*, we can pass any context though one void* parameter by passing the address of context.

    Here is another example :

    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);
    }
    

    (function,context) pair like &constant_function,&context is the C-style closure.
    Each function(F) that needs a closure must has one context parameter which will be passed to closure as its context. And the caller of F must use a correct (f,c) pair.

    If you can change the signature of function to fit to C-style closure, your code will be simple and machine-independence.
    If couldn't (function and apply is not written by you), try to persuade him to change his code.
    If failed, you have no choice but to use some closure libraries.

提交回复
热议问题