C - dynamic function call without a function pointer
Asked Answered
R

5

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?

Rivulet answered 12/3, 2013 at 22:24 Comment(2)
There is basically no way to do this in a platform-independent way.Center
Sorry, you can't pass varargs into a varargs function portably. C just does not support the necessary reflection.Jadwiga
I
7

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

Iconoscope answered 15/3, 2013 at 7:54 Comment(1)
Could you please elaborate a bit more on the hash function for quicker name search? Thanks.Fuzee
M
4

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

Mongolia answered 12/3, 2013 at 22:26 Comment(1)
can I do this kind of reflection with C++? (I still want to call C functions)Rivulet
V
3

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

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

Vibratile answered 13/3, 2013 at 1:25 Comment(0)
A
2

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.

Asbestos answered 12/3, 2013 at 22:58 Comment(0)
Q
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.

Quintile answered 29/4 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.