如何通过字符串存储类型并将其传递给 C++ 中的模板函数?

问题描述 投票:0回答:0

我有一些这样的代码,我想加载一个 dll 文件并从中选择一个函数来执行。:

// this is function's parameter define
struct Parameter
{
    std::string type;           // int
    std::string value;          // Local.X
};
using ParameterList = std::list<Parameter>;

// this is function's moudle define
struct ModuleFunction
{
    std::string path;            // dll file path
    std::string rawName;         // ?Add@@YAHHH@Z
    std::string undName;         // int __cdecl Add(int,int)
    std::string returnType;      // int
    std::string callConvention;  // __cdecl
    std::string name;            // Add
    ParameterList params;
};

// this is value define. a value is created by manual. I can get it from DataManager.
struct Value
{
    std::string name;           // value name, like: Local.X
    std::string type;           // value type, like: int, double, string, ...
    void* value;                // stored value, like: 5, 1.0, "abc", ...

    int toInt() const { ... };
    double toDouble() const { ... };
    std::string toString() const { ... };
};

// run module function
void run(const ModuleFunction& module)
{
    DllCaller calller(module.path); // load dll from module.path

    /*
    run DllCaller::dllCall() according to function's param counts
    DllCaller::dllCall() is a template function. it has variadic parameters. like:
    template <class RETTYPE = void, class... PARAMTYPES>
    RETTYPE DllCaller::dllCall(const string& callConvention, const string& fnName, const PARAMTYPES& ...params) { ... };
    */
    switch (module.params.size()) 
    {
        case 0:
            {
                if (module.returnType == "int")
                    auto ret = caller.dllCall<int>(module.callConvention, module.rawName);
                else if (module.returnType == "double")
                    auto ret = caller.dllCall<double>(module.callConvention, module.rawName);
                else if (module.returnType == "string")
                    auto ret = caller.dllCall<string>(module.callConvention, module.rawName);
            }
            break;
        case 1:
            {
                const Parameter& param = module.params[0];
                const Value& value = DataManager::getValue(param.value);
                if (module.returnType == "int")
                {
                    if (value.type == "int")
                        auto ret = caller.dllCall<int>(module.callConvention, module.rawName, value.toInt());
                    else if (value.type == "double")
                        auto ret = caller.dllCall<int>(module.callConvention, module.rawName, value.toDouble());
                    else if (value.type == "string")
                        auto ret = caller.dllCall<int>(module.callConvention, module.rawName, value.toString());
                }
                else if (module.returnType == "double")
                {
                    if (value.type == "int")
                        auto ret = caller.dllCall<double>(module.callConvention, module.rawName, value.toInt());
                    else if (value.type == "double")
                        auto ret = caller.dllCall<double>(module.callConvention, module.rawName, value.toDouble());
                    else if (value.type == "string")
                        auto ret = caller.dllCall<double>(module.callConvention, module.rawName, value.toString());
                }
                else if (module.returnType == "string")
                {
                    if (value.type == "int")
                        auto ret = caller.dllCall<string>(module.callConvention, module.rawName, value.toInt());
                    else if (value.type == "double")
                        auto ret = caller.dllCall<string>(module.callConvention, module.rawName, value.toDouble());
                    else if (value.type == "string")
                        auto ret = caller.dllCall<string>(module.callConvention, module.rawName, value.toString());
                }
            }
            break;
        case 2:
            break;
        case 3:
            break;
        case 4:
            break;
    }
}

因为我不知道函数有多少参数,也不知道参数类型是什么,所以代码非常“难”和“丑”以适应各种情况。是否可以将参数类型字符串转换为真实类型并传递给函数?或者一些更好的解决方案?

c++
© www.soinside.com 2019 - 2024. All rights reserved.