How can I call a C++ function from a string?
Instead of doing this, call the method straight from string:
void callfunction(const char* callthis, int []params)
{
if (callthis == "callA")
{
callA();
}
else if (callthis == "callB")
{
callB(params[0开发者_JS百科], params[1]);
}
else if (callthis == "callC")
{
callC(params[0]);
}
}
In C# we'd use typeof() and then get the method info and call from there... anything we can use in C++?
Create a std::map made of strings and function pointers. Create the map with all of the functions that you will want to call.
There are other ways to do it, involving symbol tables and dynamic loaders but those ways are not portable or friendly.
Other solutions are variations on the same theme:
switch (callthis)
{
case FUNCA: callA(); break;
case FUNCB: callB(params); break;
... etc.
}
Or search an array of stuctures:
struct {
char *name;
TFunc f;
} funcdefs [] = {
{"callA", callA},
{"callB", callB},
{"callC", callC},
... etc.
{NULL, NULL}
};
for (int j = 0; funcdefs [j] .name; ++j)
if (!strcmp (funcdefs [j] .name, callthis))
{
funcdefs [j] .f (params);
break;
}
You could also look at the answers to How can I add reflection to a C++ application? for information about RTTI, the reflection mechanism in C++.
Good luck.
Alternative: You could use array of function pointers and call the desired function using its index.
typedef void (*TFunc)(int, int);
TFunc arrptr[100];
void callFunction(int index, int params[])
{
(*arrptr[index])(params[0], params[1]);
}
May not be an option, but if you can use managed c++ (C++/CLI), you can do this just like you can in C#. This will require .NET though...
There is no good way of automatically doing what you ask. I'd consider two different ways, depending on how many functions you think will need to be called:
If there are only a few functions, stick with the code you have (note that if you wish to use const char*, you can't compare these strings with the == operator. You can use "strcmp()", by doing an "#include < cstring>").
If there will be many functions, or if you will be adding and removing functions from your list often, then you might want to use "std::map". This will map the function name string to a function pointer. I would probably wrap this in a class for ease-of-use:
class Str2Fun {
std::map<std::string, (void*)(int**)> data;
public:
void add( const char *funName, (void*)(int**) funPtr );
void call( const char *funName );
};
general impossibility
In pure standard C++11, you cannot really achieve that goal (calling a function from its name, given by some arbitrary string at runtime) easily, if you want to call any arbitrary possible function of your program (or of libraries used by it) from the function name. You could indeed embed an interpreter (e.g. Lua or GNU guile), as suggested by xtofl's answer.
keeping an association from name to functions
If you know the set of potentially callable functions, and if they share a common signature (e.g. typedef int signature_T(int[])
, you might use simply an association from names to functions, e.g. some std::map<std::string,std::function<signature_T>>
; BTW, the new features of C++11 (closures, std::function
, auto
, lambdas) should help a lot.
using dynamic linking facilities such as dlsym
on POSIX
If you restrict yourself to a POSIX system like Linux, you could consider some other trick: use dlsym(3) and dlopen(3) to get a function pointer from some unmangled name. So you would declare the functions you want to call thru their name as extern "C"
(to disable name mangling), you would link your program with -rdynamic
and with the -ldl
library. You would either dynamically load your plugins with dlopen
-or get the main program handle by dlopen
-ing NULL
- and fetch a function pointer from its name using dlsym
. Read C++ dlopen mini howto and Drepper's How To Write Shared Libraries paper.
(Windows also have nearly equivalent facilities to dlsym
since it also has a dynamic linker; but I never used Windows)
Some C++ framework libraries (Qt, POCO) are wrapping the dynamic loading of plugins in an OS-independent way.
calling arbitrary functions using libffi
There is an issue regarding calling functions of arbitrary signature. You absolutely need to know the signature (at least at runtime, and often at compile time) when calling any function in (or from) C or C++ (because the ABI dictates various calling conventions). You could use the libffi:
Some programs may not know at the time of compilation what arguments are to be passed to a function. For instance, an interpreter may be told at run-time about the number and types of arguments used to call a given function. Libffi can be used in such programs to provide a bridge from the interpreter program to compiled code.
Just-In-Time generation of machine code
At last, you could generate some machine code at runtime using some JIT library : simple JIT libraries like GNU lightning, libjit, asmjit are able to generate quickly some rather slow machine code, or complex compiler based JIT frameworks like libgccjit or LLVM, which are generating optimized and fast machine code (but need significant generation time, like a compiler).
generating C (or C++ code) at runtime, compiling it and dlopen
-ing it
A related trick would simply generate some C or C++ code in a temporary file /tmp/foobar.c
, fork a compilation of it into a plugin (so ask for position independent code) with gcc -fPIC -O -shared /tmp/foobar.c -o /tmp/foobar.so
, then dynamically load that temporary plugin using dlopen
. I am using such a trick in MELT (a Lispy domain specific language to extend and customize GCC, available free software GPLv3). In practice, compilers are fast enough today to even permit such use interactively: the user could type a simple expression in some DSL, the infrastructure is translating that DSL to C code then forking the compilation of that code into a plugin which is later dlopen
-ed. This is fast enough in practice for interactive use (since the generated C code would have a few hundred lines per interactive expression, and compiling that takes a fraction of a second).
other programming languages
Some programming languages are homoiconic and/or have some eval
facility, or enable multi-stage programming. Some implementations have even the ability to generate quite efficient machine code at runtime, in particular SBCL is always translating to machine code every expression, even in its read-eval-print loop.
You could wrap your function declarations into an interpreted language (like Lua or Perl or Python (boost has some nice framework for that) ). Then use that language to call your code 'by string'.
These languages/wrappers are built to do such things. C++ isn't, so you will put a lot of effort in adding support for it.
精彩评论