Dynamically creating functions in C

前端 未结 10 1582
-上瘾入骨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:05

    It looks like you're coming from another language where you commonly use this type of code. C doesn't support it and it although you could certainly cook up something to dynamically generate code, it is very likely that this isn't worth the effort.

    What you need to do instead is add an extra parameter to the function that references the matrix it is supposed to work on. This is most likely what a language supporting dynamic functions would do internally anyway.

    0 讨论(0)
  • 2020-12-09 11:11

    One way of doing would be to write a standard C file with the set of functions you want, compile it via gcc and the load it as a dynamic library to get pointers to the functions.

    Ultimately, it probably would be better if you were able to specify your functions without having to define them on-the-fly (like via having a generic template function that takes arguments that define its specific behavior).

    0 讨论(0)
  • 2020-12-09 11:11

    This mechanism is called reflection where code modifies its own behavior at runtime. Java supports reflection api to do this job.
    But I think this support is not available in C.

    Sun web site says :

    Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.

    Drawbacks of Reflection

    Performance Overhead Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

    Security Restrictions

    Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.

    Exposure of Internals

    Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform. .

    0 讨论(0)
  • 2020-12-09 11:12

    Using FFCALL, which handles the platform-specific trickery to make this work:

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

    (Untested since I don't have FFCALL currently installed, but I remember that it works something like this.)

    0 讨论(0)
  • 2020-12-09 11:13

    If you want to write code on the fly for execution, nanojit might be a good way to go.

    In your code above, you're trying to create a closure. C doesn't support that. There are some heinous ways to fake it, but out of the box you're not going to be able to runtime bind a variable into your function.

    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题