简体   繁体   中英

array of functions, names, and arguments

I'm trying to use function that input (from file) - by they names.

For example - In the file I wrote

     functionOne(1,2)

I successed to separate the function name and his arguments to different array - now I have:

    funcName[] = functioOne
    funcArg[0] = 1
    funcArg[1] = 2

But, now I stuck - how I can use it? I tried to make an array of pointers to the functions, but Have not idea how to use it. Any suggestion? Thanks

C doesn't have introspection . It's not possible, during runtime, to get or call a function from a string.

There are workarounds though. For example you can create a table containing the name of the function and a pointer to the function. Then you can search this table to find the function to call.

Perhaps something like

void functionOne(int arg1, int arg2)
{
    ...
}

struct
{
    char *name;
    void (*function)(int, int);
} functions[] = {
    { "funcitonOne", &functionOne },
};

To make it more generic, when you have many functions taking different amount of arguments, it's a little harder. Then you could instead of passing arguments like normal, pass an array containing the arguments:

void functionOne(int *arguments)
{
    // arguments[0] is the first arguments, etc.
    ...
}

Modify the function pointer in the structure accordingly.

If the types of arguments differ as well, then you could use structures with a type-tag and a union for the values.

You can't do the thing you want in C. The closest you can do is, keep an array of function pointers which will be pointing towars the respective functions. Also keep a array of strings which is exactly as per the same index as that of other array. Now whenever you get a function name - you just parse it, compare and get the appropriate function pointer based on the index of the matched string.

How to send the arguemnts - well to do that I would say you go about this - when you know which function you will have to call, you parse the arguments from the file itself (You will know that this function will take 2 arguemnts - so you will get the line and parse it to int and double as it is expected and then you will call it accordingly).

In general, you cannot do what you want in portable C11 (read n1570 ), as explained by others: function names are a compile-time thing and are unknown at execution time. The C programming language doesn't have reflection and/or introspection . BTW, a function might even "disappear" during optimized compilation (so don't "practically" exist at runtime, but your program behaves as-if that function exists), in the sense that it has been inlined or removed from the executable . However, C has function pointers (whose type describes the signature of the indirectly called function); practically speaking, they point to machine code .


But if you code an application program on an x86-64 computer running eg Linux, you might sometimes have some workarounds, using some "dirty" tricks, specific to that operating system and instruction set architecture :

  • given some string like "functionOne" (practically, of type const char* ), you could get a function pointer to it (eg the functionOne , provided it has extern linkage ) -thru dynamic linking facilities- using dlopen(3) with a NULL path, then dlsym(3) . BTW the reverse mapping (from addresses to names) is available thru dladdr(3) .

  • given a function pointer (or actually any valid address in your virtual address space pointing inside some executable code segment ), you could call it indirectly if the signature of that function is known at compile time (it is given in the type of that function pointer).

  • if you want to call an arbitrary function with arbitrary signature and arbitrary arguments only known at run-time , you might use the libffi . It knows the ABI of your system.

  • a possible trick is also to emit some temporary file /tmp/emittedcode.c containing C code (at runtime), fork a compilation process into a temporary plugin (eg gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so ), and dynamically load that temporary plugin /tmp/emittedplugin.so with dlopen(3) . Be sure to clean the mess (eg remove all temporary files, perhaps using atexit(3) ) at program termination.

  • perhaps you want to generate some machine code at runtime; then consider also some JIT compiling library such as GCCJIT , LLVM , libjit , asmjit .

If your PC is not running Linux, you might find equivalent stuff for your OS and computer. Read Operating Systems: Three Easy Pieces to learn more about OSes in general. Read the documentation of your particular OS (for Linux, read first the ALP or some newer book on Linux programming, then intro(2) , syscalls(2) , elf(5) and related pages).


BTW, if you just want to call functions from your program (from names in some input file), you might instead build at initialization some hash table (or map , perhaps a red-black tree ) associating function names to function pointers, like suggested in this other answer.

Maybe you want some homoiconic programming language having some eval primitive . Look into Common Lisp. Be aware of SBCL , it is compiling into dynamically generated machine code at most REPL interactions.

Maybe you are writing some interpreter (that is often more difficult and time consuming than you think, read the Dragon Book ). Consider perhaps embedding and using an existing one, such as Guile or Lua .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM