Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - dynamic function call without a function pointer

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?

like image 639
matg Avatar asked Mar 12 '13 22:03

matg


4 Answers

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

like image 55
assemblerbot Avatar answered Oct 28 '22 07:10

assemblerbot


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

like image 28
Chuck Avatar answered Oct 28 '22 06:10

Chuck


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

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

like image 43
awn Avatar answered Oct 28 '22 07:10

awn


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.

like image 2
Mats Petersson Avatar answered Oct 28 '22 07:10

Mats Petersson