How to call a function using its name as a string?

Hi, guys!

I got a problem. I need to call several functions based on a previous statement and I have a string database of function's names.

Ex.: If my code finds a "+" sign inside a user-entered string, it will search database to find-out the function's name is "add". Another field of the database informs that "add" has three arguments.

So, the question is if there is a way to do
>> XOXOXOX("add(1,2,3)");
and call my "add" function to return 6 as the answer? (XOXOXOX is a possible C++ command to do this)

If anybody knows MATLAB, the way I want to do this is the same as "EVAL" function implemented in MATLAB.

Hope anybody could help me on this.

Greetings,

Igor

You can't.

The closest thing you could do is make a map with a string for the commands being a key and a function pointer being the data.
C++ isn't particular famous for any kind of reflection or "eval" statements. There are only two common ways I am aware of how to solve this:

First solution: Use firedraco's advice. Somewhere in your code at the beginning of your program, initialize a map with pointer-to-functions and the name of the function. The tricky part here is that you probably have a lot of different possible call signatures for your functions. Some are called with one parameter, others with two. Some return an int, some float, other void etc..

You can either make one map for each signature, but that isn't particular easy to maintain! Or you use the evil "reinterpret_cast" to cast between function pointers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// forward declaration
int add(int, int);
int inverse(int); 

std::map<int, void*> fnMap;
int main() {
    fnMap["add"] = &add;
    fnMap["inverse"] = &inverse;
}

... // later when you need to call it:

if (signature == "int(int)")
    result = reinterpret_cast<int(*)(int)>(fnMap[name])(param1);
else if (signature == "int(int,int)")
    result = reinterpret_cast<int(*)(int,int)>(fnMap[name])(param1, param2);
...


Remember: reinterpret_cast is fragile. Sneeze and you get a segfault.


For the second solution, use DLL's (or .so under linux) and export all functions there. Then you can use platform dependend ways of calling functions dynamically from their name.

Ciao, Imi.
None of that makes any sense whatsoever. First of all, you appear to be implicitly converting C strings to ints on lines 7 and 8. Second, casts between function pointer types are illegal.

The way I'd do it is something like this (replace void * with your favorite type, such as 'ParameterType'):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
typedef void *(*fp)(void **,int);

struct function_object{
	std::string name;
	int params;
	fp pointer;
	//(I'm probably forgetting some constructor that's needed for the class to
	//be used in an std::set.)
	function_object(const std::string &n):name(n),params(0),pointer(0){}
	function_object &operator()(int p){ this->params=p; return *this; }
	function_object &operator=(fp p){ this->pointer=p; return *this; }
	bool operator<(const function_object &b){ return this->name<b.name; }
};

void *add(void **p,int n){
	//check that n>=2, if you're so inclined
	void *r=(void *)new int(*(int *)p[0]+*(int *)p[1]);
	delete (int *)p[0];
	delete (int *)p[1];
	return r;
}

int main(){
	std::set<function_object> functions;
	functions.insert(function_object("add")(2)=f);
	return 0;
}
First of all, you appear to be implicitly converting C strings to ints on lines 7 and 8.

Ups. Sorry, you're right. Typo. Better make it "std::map<std::string, void*> fnMap;"


Second, casts between function pointer types are illegal.

I thought they are implementation defined behaviour? IIRC, casting between function pointers were the main reason the standard includes reinterpret_cast. I hoped I made it clear enough that casting this way is not a good idea, but I was under the impression that it is possible for most of the compilers most of the time.

E.g. casting some normal function pointer into a member function pointer most probably won't work alltogether.

But I agree with your version. It's better, so if the OP is able to change the signatures of his functions, that's a good way to do it. He should go for that instead and unify the signatures of all dispatched functions.

(The DLL-approach would still work as alternative.)

Ciao, Imi.
Last edited on
IIRC, casting between function pointers were the main reason the standard includes reinterpret_cast. I hoped I made it clear enough that casting this way is not a good idea, but I was under the impression that it is possible for most of the compilers most of the time.
No. It's absolutely illegal. That doesn't mean that it's not supported. Any Windows or UNIX compiler that wants to allow dynamic linking has to allow casting from void * to a C function pointer. But that's a special situation because a) there's no other way to do it, since the POSIX and WinAPI functions return generic pointers, and b) the platforms are known to use pointers to data and code of the same size.
Last edited on
i dont know wether it fits or not, but "calling" the function via its name is possible using dll´s ... (at least in windoof)... you search for the function´s name within the dll and get back a pointer to it...

but you need to disable name mangling...
standard comp. sci. answer to all this, is to parse the expression into a tree and convert it into a stack (ie convert from infix to postifx). Then it's dead easy to evaluate the expression.
Topic archived. No new replies allowed.