C++通过字符串名称调用不同的函数

sku*_*tal 7 c++ boost function-pointers visual-studio-2010

我对C++比较陌生 - 我在6年多前就开始学习它了,但直到几个月前才开始使用它.

场景是什么:

  • 具有大量模块的相当大的系统.

期望的输出:

  • 模块(即X)"暴露"某些要通过网络调用的函数,并将结果发送回调用者(即Y)
  • 调用者Y不知道关于X的任何信息,尽管库(函数名和参数)暴露了什么.
  • 从库中调用X中的函数必须通过从Y接收的字符串或一组字符串来进行,因为也会有参数.

理想情况下,我想要的是具有可变返回/参数类型或某种类型擦除的尽可能通用的东西 - 因为我不知道每个模块将要暴露哪些函数.我认为用C++运行这样的东西是非常有意义的.但希望通过预先确定的可能返回/参数类型,这是可行的.通信现在不是问题,重要的是在模块方面应该做什么.

问题:

  • 是否有可能使用C++和Boost完成这样的事情?如果有人可以给我一些指导 - 文学/教程/(伪)代码示例等等,我会非常感激.我不希望这里有完整的解决方案.

可能的方法:

关于我可以/应该使用哪些语言的"功能",我有点迷失 - 这主要是由于我在项目中的限制.

我想过使用Variadic模板并发现下面的问题,这确实有帮助,唯一的问题是VS2010不支持Variadic模板.

具有任何参数列表的函数的泛型函子

经过网络上的一些广泛研究,我得到的最接近的答案是:

指向不同返回类型和签名的函数的指针的映射

情景几乎相同.然而,在我看来,OP之前已经知道他将使用的函数的返回/参数.由于我的声誉很低(我刚刚加入),我很遗憾不能在那里询问/评论任何内容.

TBH我不太清楚如何完成所选答案的解释.

使用map是一种方法,但我必须存储包含函数指针的对象(也在问题中回答),但是由于可以在用户提供的代码中看到它,它确实有一些硬编码的东西,我不想拥有.

进一步澄清:

  • 是的,我被限制使用C++和VS2010 SP1.
  • 不,尽管Boost,我不能使用任何其他第三个库 - 能够使用一些反射库如CPGF http://www.cpgf.org/会很棒(即使我不是100%肯定,如果那是什么我真的需要)

次要编辑: - 脚本语言绑定(如LUA)确实是一种方法,但我不想将其包含在项目中.

我希望有人可以解释这个问题!

提前感谢任何输入!

Net*_*ire 2

看起来你需要一个小反射模块。例如,我们有一个方法信息结构,例如:

struct argument_info {
    std::string name;
    std::string type;
    std::string value;
}

struct method_info {
    std::string method_name;
    std::string return_type;
    std::list<argument_info> arguments;
}
Run Code Online (Sandbox Code Playgroud)

然后编译一个包含所有导出函数的dll

extern"C" __declspec(dllexport) void f1(int a, int b){/*...*/}
extern"C" __declspec(dllexport) int f1(std::string a, int b, char* c){ return x; }
Run Code Online (Sandbox Code Playgroud)

在解释器的代码中:

void call_function(method_info mi, argument_info& t_return)
{
    /* let g_mi be a map, where key is a std::string name of the method and the 
       value is method_info struct */ 
    if(!g_mi->find(mi.method_name))
        throw MethodNotFindException

    if(g_mi[mi.method_name].arguments.size() != mi.arguments.size())
        throw InvalidArgumentsCountException;

    for(int i = 0; i < g_mi[mi.method_name].arguments.size(); i++)
    {
        if(g_mi[mi.method_name].arguments[i].type != mi.arguments[i].type)
            throw InvalidArgumentException;
    }

    t_return = module->call(mi.arguments); 
}
Run Code Online (Sandbox Code Playgroud)

我希望它可以帮助你。