2

Is it possible to assign with cast to a function pointer a string or char array and then run it?

I have defined a few functions int f1();, int f2();, and so on

In the main() function I have read a string fct_name and declared a pointer to function int (*pv)();

I need to do something like this:

the fct_name can have values "f1" , "f2" and so on..

pv = (some sort of cast)fct_name;

pv();

My point is I want to avoid conditional instructions in favor of direct assignment (because I have a large number of functions in my program)

The code must obviously run.

Dan Fego
  • 13,644
  • 6
  • 48
  • 59
Alexandru N. Onea
  • 423
  • 2
  • 6
  • 18

3 Answers3

1

A variant of Carey's answer, in case you're on a *nix system. dlopen() opens up your library. RTLD_LAZY tells the loader to not bother resolving all the library's symbols right away, and to wait for you to try to access them. dlsym() looks up the symbol in question.

Edit: Updated the snippet to better fit your clarification:

#include <dlfcn.h>

int main(int argc, char *argv[])
{
    void *handle = dlopen("libexample.so", RTLD_LAZY);
    if (handle == NULL) {
        // error
    }

    char fct_name[64];

    // read input from terminal here

    void *func = dlsym(handle, fct_name);

    if (func != NULL) {
        // call function here; need to cast as appropriate type
    }
}

libexample.so would be a library with your functions, compiled as a shared library, like so:

gcc -Wall -o libexample.so example.c -shared -fPIC

That being said, if you're going to the trouble of compiling a shared library like this, you'll probably just want to call the functions in your binary. You can do that if you link your library in at compile-time:

gcc -Wall -o test test.c -L. -lexample

-L. tells the linker to look for libraries in the current directory (.) and -lexample tells it to link with a library named "libexample.so". If you do this, you can just call the library functions directly within your program.

Dan Fego
  • 13,644
  • 6
  • 48
  • 59
  • 1
    Note also -- if you link with `-rdynamic`, you can use `dlsym(RTLD_DEFAULT, name)` to find a function in your executable, without ever calling dlopen... – Chris Dodd Dec 14 '11 at 22:35
1

Assuming you don't have an external library and are trying to call functions declared in your executable, you can do a lookup yourself

#define REGISTER_FUNC(name)  {#name, name}

struct funclist
{
    const char* name;
    void (*fp)(void);  //or some other signature
};

struct funclist AllFuncs[] = {
    REGISTER_FUNC(f1),
    REGISTER_FUNC(f2),
    REGISTER_FUNC(f3),
    {NULL,NULL}  //LAST ITEM SENTINEL
 };

Now you can lookup your variable fct_name in AllFuncs. You can use a linear search if the number is small, or insert them all into a hash table for O(1) lookup.

Alternately, if your names really are f1, f2, etc. you can just do

   void (*FuncList)(void)[]  = {NULL, f1,f2,f3};
   ...
   int idx = atol(fct_name+1);
   if (idx && idx < MAX_FUNCS)  
       FuncList[idx]();
AShelly
  • 34,686
  • 15
  • 91
  • 152
0

You can't cast a char array to a function just because the array happens to contain the name of a function. What you need to do is put your function(s) in a DLL and then do this:

HMODULE dll = LoadLibrary("foo.dll");
pv func = (pv)GetProcAddress(module, fct_name);
Carey Gregory
  • 6,836
  • 2
  • 26
  • 47