0

I want to write a program which reads from stdin : scanf("%s %s", foo, args); then run function foo ( which was defined in program before ) with arguments : foo(args); I don't know how to do this in C . I could easily do this in Shell before but seems difficult in C

phoxis
  • 60,131
  • 14
  • 81
  • 117
alireza_fn
  • 884
  • 1
  • 8
  • 21
  • wrap this around a function as `my_scanf` take input in that using `scanf` and then call `foo` on entered input within same function – P0W Sep 30 '13 at 16:06
  • @P0W: he is talking about interpreting i think. – phoxis Sep 30 '13 at 16:07
  • 1
    Did you try searching this site first ? There are similar question: http://stackoverflow.com/questions/1118705/call-a-function-named-in-a-string-variable-in-c and http://stackoverflow.com/questions/2184613/is-it-possible-to-call-a-c-function-given-its-name-as-a-string – Sage Sep 30 '13 at 16:11

2 Answers2

6

There's no solution for this problem which is generalized and cross-platform/standard at the same time.

The non-general solution that doesn't rely on non-standard extensions: store name and function pointer pairs in an array, perform search, call function by pointer. For example:

struct namedfunc {
    const char *name;
    void (*fptr)(void);
} fvect[3] = {
    { "foo", foo_impl },
    { "bar", bar_impl },
    { "baz", baz_impl }
};

char buf[0x100];
fgets(buf, sizeof buf, stdin);
char *p = strchr(buf, '\n');
if (p != NULL)
    *p = 0;

for (size_t i = 0; i < sizeof fvect / sizeof fvect[0]; i++) {
    if (strcmp(buf, fvect[i].name) == 0) {
        fvect[i].fptr();
        break;
    }
}

The more general solution that relies on dynamic loading being available: use the dlopen() API, like this:

void *hndl = dlopen(RTLD_SELF, RTLD_LAZY); // try NULL if RTLD_SELF doesn't work
void (*fptr)(void) = dlsym(hndl, buf);
if (fptr != NULL)
    fptr();

dlclose(hndl);
2

Another hard to debug, highly fragile solution would involve compiling with debug symbols (or a map file), parsing them and calling the function dynamically. That's crazy.

Reasonably though, do you really want every single function in your program callable in this way? Including main? Probably not. Well then, identify a set of functions that should be callable in this way, and build an array of structures that would contain a function name and a function pointer. When presented with function name upon input, scan the array for that function, find the function pointer and call. If they have different prototypes, add another member that would describe the kind of parameter(s) the function would expect. (EDIT: the answer above suggests the same and provides details)

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • 1
    OMG your suggestion is really crazy! It's so insane I must implement it just for fun's sake! :D –  Sep 30 '13 at 16:12
  • 1
    Debugger does it. Just sayin'. :))) MAP file would be easier to parse probably, and it has global functions' start addresses - all you need, in theory. To figure out the offset of the code section in the process' address space, first look up the currently executing function in the MAP file. For bonus points, feel free to deduce the prototype from C++ name decoration. – Seva Alekseyev Sep 30 '13 at 16:28