[英]use std::string to call a function in C++11
I want to use string value to call a function. Is this possible?我想使用字符串值来调用 function。这可能吗? Can someone please show some implementation.有人可以展示一些实现吗? I would appreciate it.我会很感激。
class obj {
int num1;
int num2;
}
int func1(obj o) {
return o.num1 + o.num2;
}
// This is an example data set. This map would be populated with values in the map below with some piece of code.
std::map<std::string, std::string> funcNameMap = {{"func1", "func1"}};
int someFunction(std::string funcName, obj o) {
// Get the value associated with the string "funcName" i.e. "func1".
// Calls function "func1" with value "o" and returns the value.
}
int main(){
obj o;
o.num1 = 1;
o.num2 = 2;
auto x = someFunciton("func1", o);
std::cout << x << std::endl;
return 0;
}
I am writing a program that collect metric data.我正在编写一个收集指标数据的程序。 I want to execute a particular function for a particular metric.我想针对特定指标执行特定的 function。 I would name all the functions same as the metric name so that when I give metric name as input (string) it would execute a particular function. I don't want if-else for executing function based on the metric name input as my program is collecting over a hundred metric.我会将所有函数命名为与度量名称相同,这样当我将度量名称作为输入(字符串)时,它将执行特定的 function。我不希望 if-else 根据作为我的程序输入的度量名称执行 function正在收集一百多个指标。 It would look pretty awkward to have that may if-else.如果使用 may if-else 看起来会很尴尬。 That is why I am trying to do something this way.这就是为什么我试图以这种方式做某事。
Want something that works for both OSs windows/linux想要适用于两种操作系统 windows/linux 的东西
One solution is to create a mapping from function name to function itself.一种解决方案是创建从 function 名称到 function 本身的映射。 We know that a function is a pointer in C/C++, so we can easily do this after confirming the type of the function pointer.我们知道function在C/C++中是一个指针,所以我们在确认function指针的类型后就可以很容易的做到这一点。 In your case, the target function type is int (*)(obj)
.在您的情况下,目标 function 类型是int (*)(obj)
。
Code snippet:代码片段:
#include <iostream>
#include <map>
#include <string>
class obj {
public:
int num1;
int num2;
};
int func1(obj o) { // type: int (*)(obj)
return o.num1 + o.num2;
}
// create the mapping from name to function
std::map<std::string, int (*)(obj)> funcNameMap = {{"func1", func1}};
int someFunction(std::string funcName, obj o) {
// Get the value associated with the string "funcName" i.e. "func1".
// Calls function "func1" with value "o" and returns the value.
auto fn = funcNameMap.at(funcName);
return fn(o);
}
int main(){
obj o;
o.num1 = 1;
o.num2 = 2;
auto x = someFunction("func1", o);
std::cout << x << std::endl;
return 0;
}
Edit : Update according to the comment, use dynamic shared library to avoid manually creating the mapping.编辑:根据评论更新,使用动态共享库避免手动创建映射。 I assume you are using Linux.我假设您使用的是 Linux。
First, move class definition and the type of target functions into a separated header obj.hpp
:首先,将 class 定义和目标函数类型移动到单独的 header obj.hpp
:
class obj {
public:
int num1;
int num2;
};
// type of target functions
typedef int (*ftype)(obj);
Collect target functions to a separated file functions.cpp
to build dynamic shared library.将目标函数收集到单独的文件functions.cpp
以构建动态共享库。
#include "obj.hpp"
extern "C"
int func1(obj o) {
return o.num1 + o.num2;
}
extern "C"
int func2(obj o) {
return o.num1 - o.num2;
}
In the third file main.cpp
, we retrieve functions from the library according to the function name.在第三个文件main.cpp
中,我们根据 function 名称从库中检索函数。
#include <iostream>
#include <map>
#include <dlfcn.h>
#include <cassert>
#include "obj.hpp"
// name mapping: public name to inner name
std::map<std::string, std::string> funcNameMap = {{"add", "func1"}, {"sub", "func2"}};
int retrieve_fn(void *dl_handler, std::string funcName, obj o) {
assert(dl_handler != NULL && funcNameMap.count(funcName) != 0);
auto real_fn_name = funcNameMap[funcName];
auto fn = (ftype)dlsym(dl_handler, real_fn_name.c_str());
auto dl_err = dlerror();
if (dl_err) {
std::cerr << "Load failed: " << dl_err << std::endl;
return -999;
}
return fn(o);
}
int main(){
obj o;
o.num1 = 1;
o.num2 = 2;
// open dynamic shared library
auto dl_name = "./functions.so";
auto dl_handler = dlopen(dl_name, RTLD_LAZY);
auto dl_err = dlerror();
if (dl_err) {
std::cerr << "Open failed: " << dl_err << std::endl;
return -1;
}
auto x = retrieve_fn(dl_handler, "add", o);
std::cout << x << std::endl;
x = retrieve_fn(dl_handler, "sub", o);
std::cout << x << std::endl;
dlclose(dl_handler);
return 0;
}
functions.cpp
.从functions.cpp
构建一个动态共享库。$ g++ functions.cpp -shared -fPIC -o functions.so
main.cpp
.从main.cpp
构建一个可执行文件。$ g++ main.cpp -ldl -o main
$ ./main
3
-1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.