• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 279
  • Last Modified:

Function Pointer in C

In one of my prject, I want to convert String/Char * to a function pointer. String/Char * contains the name of the function decided at runtime. How to write a code so that after type-casting the char * to function pointer, I can execute the function by just calling it?

Further, I want to add RunTime to the list of functions without modifying the code. The only thing, I know, is the string which I am passing, represents the name of the function. Function does exist by that NAME. At runtime, I can select any function for calculation. This code must work across different platforms and OS
0
prafulla
Asked:
prafulla
  • 5
  • 3
  • 2
  • +5
1 Solution
 
ecwCommented:
You can't do this by casting.  A quick in easy way, is to create a lookup table between function name and function.  Then when your code must call a function by name, search the table for the name, and if found call the associated function.  eg.

#include <string.h>

/* typedef'ing saves hassle later */
typedef char *(*fptr)();

struct {
  char *name;
  fptr func;
} f_map[] = {
  { "strcat",  strcat },
  { "strcpy", strcpy },
  { 0, 0 }
} ;

fptr f_lookup(char *name)
{
int i;
  for (i = 0; f_map[i].name; ++i) {
    if (! strcmp(f_map[i].name, name)) return f_map[i].func;
  }
  return 0;
}

/* and to use it */
void somefunc(char *s1, char *s2)
{
fptr func = f_lookup("strcat");
  if (func) func(s1, s2);
}

0
 
danny_pavCommented:
you might think about using an index instead of the string and using the above solution
0
 
duneramCommented:
and if you want to get a little fancier, take the string with the above method, and generate a hash (index) and then use that.....

If you are in windows, and using the SDK  you can use the GetProcAddress() api to retrieve a function by text name or by export ordinal number.
0
Improve Your Query Performance Tuning

In this FREE six-day email course, you'll learn from Janis Griffin, Database Performance Evangelist. She'll teach 12 steps that you can use to optimize your queries as much as possible and see measurable results in your work. Get started today!

 
elfieCommented:
If you are working on Unix machine, some standard routine exist.

try doing a man shl_load (HPUX) or man dlload (Sun). There you will find information on how to execute routine that are present in 'some' libraries (or running program)
0
 
prafullaAuthor Commented:
Edited text of question
0
 
alexoCommented:
You can call functions by name in interpreted languages.  C is compiled.
0
 
Answers2000Commented:
There's no portable way to do this.  
You can use UNIX and Windows functions to do a platform specific way.  You can even use a double indirection and a bit of clever pre-processor magic to keep the platform specific stuff in one place.
That's the best real answer you'll get.


For a "fun" answer, I have realized in C++ you can almost do this

1. Setup a singleton class which stores a map of pointers to objects and their names.

2. Setup an abstract base class.  Base functionality of this class is to add itself into the map.

3. Each function then goes in a singleton derived class of 2

4. Use the pre-processor to hide most (I don't think all) of the horrible syntax anamolies, ' and ## pre-processor operators will prove useful here.

Of course, I'd never do this in practice...having said this I don't think this will be totally clean.
0
 
elfieCommented:
I agee with Answer2000.

There is no portable way of doing this. You can define your own "load3 routine. Inside this routine you will have some pre-compiler directives so you can write code for each individual OS.

Each OS has its specific calls (see above eg shlload and dlload)
This is needed because there are different formats of libraries and executables. (e.g. ELF format)

0
 
rbrCommented:
Sorry there will be no way to do this directly. You have to write a parser which is able to interpreted the string (=function, formula) you want to execute.
0
 
alexoCommented:
I suggest you "reopen" the question because the currently pending answer does not help you much.

>> This code must work across different platforms and OS
The only portable way to accomplish that is using a pre-compiled mapping between a string and a function pointer.  It is easier in C++ because you can use the STL for maps, etc., but it is possible in C too.  You could implement a hash table for best speed but a binary search is a good compromise too if the number of functions is not too large (say, a couple of hundreds?).

Here's a sample program that handles 3 trig functions:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

typedef double (*PFUNC)(double);

typedef struct {
    char* name;
    PFUNC pFunc;
} COUPLE;

int Compare(const void* pStr, const void* pCouple);

COUPLE map[] = { /* Must be sorted by string! */
            { "cos", cos },
            { "sin", sin },
            { "tan", tan }
};

void main()
{
    const double arg = 0.5;

    for(;;)
    {
        char name[64];
        COUPLE* result;

        printf("> ");
        gets(name);
        result = (COUPLE*)bsearch(name, map, sizeof(map) / sizeof(*map), sizeof(*map), Compare);
        if (!result)
            break;
        printf("%s(%f) = %f\n", name, arg, result->pFunc(arg));
    }
}

int Compare(const void* pStr, const void* pCouple)
{
    return strcmp((char*)pStr, ((COUPLE*)pCouple)->name);
}

It can be generalized to handle more than one argument by including a "number of arguments" field in the structure and switching on it.  The PFUNC type will have to be declared as taking an unknown number of arguments (empty parentheses) and some casting may be involved.
0
 
prafullaAuthor Commented:
I want it to be done in C as s/w on which I am working supports C integration. And we have couple of our previous C code available for current projects core items. So I don't want to rewrite them.
Thank you for the response. If anybody finds the answer. Kindly update the answer-list.

Regards!
0
 
alexoCommented:
prafulla, what's wrong with my suggestion?
0
 
ecwCommented:
Or indeed my suggestion, simple but does the job.  I think embedding a parser (in fact an interpreter) to evaluate a function is far more complex than a table lookup, and will probably rely on table lookups (switch statements anyone?) to do its job.
0
 
alexoCommented:
ecw, a simple loop (like you suggested) is quivalent to a linear search and may have to compare all the strings (worst case).  A binary search (like I suggested) needs log(N) compares and a hash table (duneram's suggestion) is the most efficient but needs the most programming effort.  Actually, the principle is the same: a mapping between a string and a pointer to function.  I have no idea why prafulla accepted a patently wrong answer.
0
 
ecwCommented:
Why bother with a binary search or hash lookup for a small data set?  Granted we don't know the number of names to lookup, but I doubt very much whether it'll approach the pint where search times, even liner search times, become and issue.  Both our examples use a data set size (2 or 3 elements) that will be faster to search linearly than using bsearch.  Note, I'm not criticising your solution, for large data sets, it'll certainly be faster, just as hashing will be faster still, but as an illustration, I think it's adequate.
0
 
alexoCommented:
>> Why bother with a binary search or hash lookup for a small data set?
Because, as you mentioned yourself, we don't know the number of names to lookup, nor the length of the strings.  I also happen to personally dislike linear searches, and if you compare our solutions you'll see that the "bother" for a binary search is virtually nil.  I agree that a hash table is an overkill.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Turn Raw Data into a Real Career

There’s a growing demand for qualified analysts who can make sense of Big Data. With an MS in Data Analytics, you can become the data mining, management, mapping, and munging expert that today’s leading corporations desperately need.

  • 5
  • 3
  • 2
  • +5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now