views:

524

answers:

12

How to process dynamic source code in C++? Is it possible to use something like eval("foo")?

I have some functions that need to be called depending on user's choice:

     void function1 ();
     void function2 ();
     ...
     void functionN ();

     int main (int argv, char * argv [])
     {
         char * myString = new char [100];
         ...
         myString = "1" //user input            
         cout << eval("function"+myString)();
     }

How is it usually done?

UPD: Based on slacy's and clinisbut's answers I think I need to make a function registry. I suppose it should be made as an array of pointers to functions. Here's the question, how do I declare an array of pointers to functions?

+15  A: 

C++ is a compiled language, and thus, there is no equivalent to "eval()".

For the specific example you mention, you could make a function registry that maps inputs (strings) to outputs (function pointers) and then call the resultant function.

There are several C++ interpreter libraries that are available, although performance will be very poor, they may accomplish what you want. Google search for "C++ interpreter". I've seen results for "Ch", "CINT" and "clipp"

slacy
However, you could dynamically invoke the compiler, tell it to produce a DLL, load that DLL and pull out and invoke your dynamically compiled function. I would be *very* slow, but you could do it (assuming that your application will run in an environment that has a compiler and linker available to it).
Aaron Maenpaa
If you wanted something faster and crazier, you could assemble the machine instructions yourself in a buffer and then call the buffer through a function pointer... though that would be basically impossible to do correctly and would be *very* platform specific.
Aaron Maenpaa
note that even on dynamic languages, using eval() would be much, much slower than the sane solution.
Javier
A: 

You can't do that in C++. It is a mandatorily-compiled language.

A lot of information that would be necessary to implement eval() is lost at run-time anyway.

alamar
The C++ Standard nowhere forbids implementation of C++ via an interpreter, which could implement an eval()-style function. The function itself would of course be non-standard.
anon
It is not possible since there's no reflection in C++.Your eval() wouldn't be able to fruitfully communicate with the rest of your (compiled) code.
alamar
There is nothing in the C++ Standard that says that C++ implementations cannot support reflection, either.
anon
+6  A: 

You could embed a C/C++ interpreter into your program if you really need this. However, you could also embed a more script-like language instead.

Naaff
+1 The sane answer!
Daniel Earwicker
+4  A: 

To answer your question of how this is usually done, the answer is: it isn't.

Having to use something like eval() is usually a design problem. If you really do need it, embed a scripting language such as Lua or Python.

Zifre
+1  A: 

I would build an array, or an STL list, of function pointers and the strings that you find that trigger the call to them. If you really need to call an arbitrary function you should investigate RTTI http://en.wikipedia.org/wiki/Run-time_type_information

Jay
How will RTTI help identify the types of function pointers, which are not polymorphic types?
bk1e
True, but all I intended was to provide a starting point. I don't believe "doing his homework for him" is as valuable as giving him a pointer to where he can learn for himself.
Jay
+2  A: 

If you put function1 .. functionN in a DLL, you could simply pull them out and invoke them by name using dlopen/dlsym which would probably get you 90% of the way you want to go.

Aaron Maenpaa
+1  A: 

The C++ language itself is not able to do that directly. But you may use plateform specific functions to call any function in a given DLL, according to user input (or whatever). For example, on Windows, look for GetProcAddress() and LoadLibrary()

Jem
+11  A: 

The real answer to your question is this:

extern "C" {
void function1 ();
void function2 ();
void function3 ();
}


 int main (int argv, char * argv [])
 {
     char * myString = new char [100];
     ...
     myString = "function1"; //user input     

     void (*f)() = dlsym(RTLD_NEXT, myString);
     f();
 }

You can obtain the function defined in your binary (by its name, if it was declared with extern "C"), and call it.

On windows, it becomes uglier, but still possible - read on GetProcAddress

alamar
Didn't slsym() return a void*? C++ requires a reinterpret_cast< > for that conversion.
MSalters
+1, this is actually an answer to the original problem. Compiling C++ on the fly looks like overkill when you just need to setup a function pointer. First answers on SO have an unfair advantage...
Jem
First answer was mine and it wasn't as good because I didn't figured exactly what does he want.
alamar
Looks like a serious hack.
the_drow
Nope, it isn't. It's basically how all plugin systems work, under the cover.
alamar
+1  A: 

This is a good case for embedding an interpreted language like LUA. If you create LUA bindings to your C++ API, you'll be able to dynamically execute your code via LUA code from your application.

toastie
+2  A: 

How about function pointers?

A: 

What you want is reflection. It's not supported by default in C++, but many people have written comprehensive reflection systems for all sorts of purposes. One that comes to mind off the top of my head is binding C++ functions to a custom scripting language.

Others have mentioned using a switch statement (or more accurately and if/else tree). This is about as simple as a reflection system is likely to come... and it is probably the best solution for your project. Reflection in C++ is a fairly advanced technique and often requires a lot of additional code... sometimes even custom preprocessors.

Also note that for security purposes, eval() is almost never something you want to be using in any language.

Dan Olson
+1  A: 

how do I declare an array of pointers to functions?

The C programmer's response to this question:

use cdecl.

cdecl> declare functable as pointer to function (int,pointer to int) returning double

double (*functable)(int , int *)

cdecl> declare functable as array 17 of pointer to function (int) returning double

double (*functable[17])(int )

Note that functions automatically convert into pointers to functions, in the same sense that arrays decay into pointers. You don't need an & to take the address of a function to put it in a pointer.

If you're in C++, it might help to use a std::map<YourFunctionPointerType> instead of an array, since you want to map strings anyway...

The OO approach:

Use polymorphism instead. It doesn't immediately solve your problems, but there's a good chance that if you're doing this it makes sense to have a class for each function.

Note that a vtable is, fundamentally, a table of pointers to functions.

Captain Segfault