Solved

Function Pointer in C

Posted on 1998-09-02
16
218 Views
Last Modified: 2012-05-04
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
Comment
Question by:prafulla
  • 5
  • 3
  • 2
  • +5
16 Comments
 
LVL 5

Expert Comment

by:ecw
ID: 1252457
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
 
LVL 3

Expert Comment

by:danny_pav
ID: 1252458
you might think about using an index instead of the string and using the above solution
0
 
LVL 2

Expert Comment

by:duneram
ID: 1252459
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
 
LVL 3

Expert Comment

by:elfie
ID: 1252460
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
 

Author Comment

by:prafulla
ID: 1252461
Edited text of question
0
 
LVL 11

Expert Comment

by:alexo
ID: 1252462
You can call functions by name in interpreted languages.  C is compiled.
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1252463
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
 
LVL 3

Expert Comment

by:elfie
ID: 1252464
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 10

Accepted Solution

by:
rbr earned 60 total points
ID: 1252465
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
 
LVL 11

Expert Comment

by:alexo
ID: 1252466
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
 

Author Comment

by:prafulla
ID: 1252467
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
 
LVL 11

Expert Comment

by:alexo
ID: 1252468
prafulla, what's wrong with my suggestion?
0
 
LVL 5

Expert Comment

by:ecw
ID: 1252469
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
 
LVL 11

Expert Comment

by:alexo
ID: 1252470
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
 
LVL 5

Expert Comment

by:ecw
ID: 1252471
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
 
LVL 11

Expert Comment

by:alexo
ID: 1252472
>> 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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now