5

I would like to call C functions (e.g. form the stdlib, math ...) dynamically. This means that my C program only knows the pointer to a random function (e.g. printf) and its signature (coded as a char array: char *, ...).

My goal is a reflectCall-function that gets a pointer to a function (&printf), a signature (somehow coded in a char[]), and the parameters as a long[] (long is not the actual datatype, one long value can also represent a double value, pointer,...).

The signature of my reflect function therefore looks like this:

long reflectCall(void *funcPointer, char[] types, long[] args)

The function should do the actual call of the function *funcPointer and finally return its result.

As a result, I can not create a pointer pointer; e.g. like this one:

int (*functionPtr)(int,int);

Can anybody give me a hint how to solve this problem or suggest any reference implementation?

2
  • There is basically no way to do this in a platform-independent way. Commented Mar 12, 2013 at 22:25
  • Sorry, you can't pass varargs into a varargs function portably. C just does not support the necessary reflection. Commented Mar 12, 2013 at 22:25

5 Answers 5

8

It is possible to do it in pure C but it is not so simple and not so quick:

  1. Create wrapper functions for all functions you want to call, such as:

    int WrapPrintf(const char* types,long* args,long* results)
    {
        // Function specific code, in this case you can call printf for each parameter
        while(*types)
        {
            switch(*types){
            case 'i':
                printf("%d",(int)*args);
                break;
            case 'c':
                printf("%c",(char)*args);
                break;
            // .. and so on
            }
    
            ++types;
            ++args;
        }
        // Return number of filled results
        return 0;
    }
    
    int WrapFoo(const char* types,long* args,long* results)
    {
        // ..function specific code..
        return 0;
    }
    
  2. Pointer to a wrapper function:

    typedef int (*TWrapper)(const char*,long*,long*);
    
  3. Create a table structure for wrapped functions:

    struct STableItem{
        const char *strName;
        TWrapper pFunc;
    };
    
  4. Create a table:

    STableItem table[] = {
        {"printf", &WrapPrintf},
        {"foo", &WrapFoo},
        {NULL, NULL}
    };
    
  5. Create interface to call any function from the table (search function by name and call it):

    int DynamicCall(const char *func_name,const char* types,long* args,long* results)
    {
        int k;
        for(k=0;table[k].strName != NULL;++k){
            if(strcmp(func_name,table[k].strName) == 0){
                return table[k].pFunc(types,args,results);
            }
        }
    
        return -1;
    }
    
  6. And finally make a call:

    long args[] = {123,'b'};
    long results[8];            // not nice but just for an example
    
    int res_count = DynamicCall("printf","ic",(long*)args,(long*)results);
    

Note: use a hash function for quicker name search

Sign up to request clarification or add additional context in comments.

1 Comment

Could you please elaborate a bit more on the hash function for quicker name search? Thanks.
5

C does not provide the facilities to do this. You'd have to write the body of the function in platform-specific ASM.

1 Comment

can I do this kind of reflection with C++? (I still want to call C functions)
4

I would to recommend you to look at libffi, whether it fits your needs...

http://sourceware.org/libffi/
http://en.wikipedia.org/wiki/Libffi

Comments

3

As explained elsewhere, there is no way to do this truly dynamically. However, if you wish to build a table of functions using pointers, and use some sort of string or index to describe what you want to do, then that would certainly be possible, in a portable way. This is not at all uncommon as a solution for various parsing and other "run code based on commands, etc".

But it does require that you use a function pointer of some sort [or cast your void * into one at some point or another]. There is no other (even nearly) portable way of calling a function dynamically in C.

Comments

0

You could use the POSIX 'dlfcn' API to dynamically get a function by its name. I don't know what the Windows equivalent is.

For C++ functions, there's name mangling, which in short is a mechanism with which C++ encodes function names and argument types, so that it is comaptible with a C linker. This will allow you to call a C++ function and specify which overload (aka what argument types) you want to call.

For C, no argument type data is kept, so a .dll or .so will keep just the name of the function. If you want to call a C function, you will have to know the signature in advance. Of course, your application could keep a table of all function names and their respective signatures, but I don't know of how much help that is going to be.

Furthermore, you need to know what the calling convention of the function is. In C++, I believe this data is encoded in the mangled name, however I'm not sure. In C, it is platform-dependant, so you have to write code for each platform for invoking a function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.