Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to call a C function, given its name as a string?

Tags:

c

function

I saw this question in one of the C puzzles!! Is this really possible?

How can I call a function, given its name as a string? is it possible to use string that is read with scanf be used directly to call a function?

i already have thought of if(strcmp(str,"string"))then call the function.

but is there any other approach?

like image 866
Vijay Avatar asked Feb 02 '10 14:02

Vijay


3 Answers

Since no mention of what is a function, nor its parameters, I would imagine it something like this:

typedef void (*foo)();
struct puzzleFoo{
   char *function_name;
   foo *fn;
};

Create a lookup table based on the structure, using a string parameter

struct puzzleFoo *Lookup(const char *function_name);

Then iterate through an array/list looking for the puzzleFoo's function_name and execute the function pointer called fn.

like image 111
t0mm13b Avatar answered Sep 24 '22 07:09

t0mm13b


With POSIX.1-2001 you should use dlopen() and dlsym(). On Windows use GetModuleHandleEx() and GetProcAddress().

Here's an example verbatim from the manual that loads the function named "cos" from the math library and determines the cosine of 2.0:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int
main(int argc, char **argv)
{
   void *handle;
   double (*cosine)(double);
   char *error;

   handle = dlopen("libm.so", RTLD_LAZY);
   if (!handle) {
       fprintf(stderr, "%s\n", dlerror());
       exit(EXIT_FAILURE);
   }

   dlerror();    /* Clear any existing error */

   /* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
      would seem more natural, but the C99 standard leaves
      casting from "void *" to a function pointer undefined.
      The assignment used below is the POSIX.1-2003 (Technical
      Corrigendum 1) workaround; see the Rationale for the
      POSIX specification of dlsym(). */

   *(void **) (&cosine) = dlsym(handle, "cos");

   if ((error = dlerror()) != NULL)  {
       fprintf(stderr, "%s\n", error);
       exit(EXIT_FAILURE);
   }

   printf("%f\n", (*cosine)(2.0));
   dlclose(handle);
   exit(EXIT_SUCCESS);
}
like image 26
Matt Joiner Avatar answered Sep 21 '22 07:09

Matt Joiner


You could be sneaky:

if (strcmp (fn, "function1") == 0) function1();
if (strcmp (fn, "function2") == 0) function2();
if (strcmp (fn, "function3") == 0) function3();

or you could use dlopen and dlsym (or equivalent) depending on your execution environment but these aren't standard C so that might not be an option.

That's about all I've got other than incredibly non-portable stuffing around with the executable file or designing hideous macros (which would most likely boil down to the collection of if statements shown above anyway, or a function pointer array of some sort).

like image 23
paxdiablo Avatar answered Sep 21 '22 07:09

paxdiablo