簡體   English   中英

使用 std::string 在 C++11 中調用 function

[英]use std::string to call a function in C++11

我想使用字符串值來調用 function。這可能嗎? 有人可以展示一些實現嗎? 我會很感激。

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;
}


我正在編寫一個收集指標數據的程序。 我想針對特定指標執行特定的 function。 我會將所有函數命名為與度量名稱相同,這樣當我將度量名稱作為輸入(字符串)時,它將執行特定的 function。我不希望 if-else 根據作為我的程序輸入的度量名稱執行 function正在收集一百多個指標。 如果使用 may if-else 看起來會很尷尬。 這就是為什么我試圖以這種方式做某事。

想要適用於兩種操作系統 windows/linux 的東西

一種解決方案是創建從 function 名稱到 function 本身的映射。 我們知道function在C/C++中是一個指針,所以我們在確認function指針的類型后就可以很容易的做到這一點。 在您的情況下,目標 function 類型是int (*)(obj)

代碼片段:

#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;
}

編輯:根據評論更新,使用動態共享庫避免手動創建映射。 我假設您使用的是 Linux。

首先,將 class 定義和目標函數類型移動到單獨的 header obj.hpp

class obj {               
  public:                 
    int num1;             
    int num2;             
};                        
// type of target functions
typedef int (*ftype)(obj);

將目標函數收集到單獨的文件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;
}

在第三個文件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;
}
  1. functions.cpp構建一個動態共享庫。
$ g++ functions.cpp -shared -fPIC -o functions.so
  1. main.cpp構建一個可執行文件。
$ g++ main.cpp -ldl -o main
  1. 運行並查看結果。
$ ./main
3
-1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM