【问题标题】:Is there C/C++ equivalent of eval("function(arg1, arg2)")?是否有 eval("function(arg1, arg2)") 的 C/C++ 等价物?
【发布时间】:2012-06-18 07:06:44
【问题描述】:

它需要一种调用函数的方法,该函数的名称存储在类似于 eval 的字符串中。你能帮我吗?

【问题讨论】:

  • 不,你最好的选择是命令模式。
  • 如果你愿意向qt的力量低头,是的:qt-project.org/doc/qt-4.8/QMetaObject.html
  • 有一些C++解释器:stackoverflow.com/questions/69539/…
  • -1 这是一个糟糕的想法,我不能凭良心鼓励它。如果你养成用eval 解决问题的习惯,你就会养成一个非常非常糟糕的习惯。您的代码会运行缓慢、效率低下、易受攻击且难以理解。
  • 所以因为这是一种不好的做法,人们不应该知道它的存在和可能性吗?一路走好伙计!凭着良心,我不能忽视你的演讲。

标签: c++ eval


【解决方案1】:

C++ 没有反射,所以你必须破解它,即。 e.:

#include <iostream>
#include <map>
#include <string>
#include <functional>

void foo() { std::cout << "foo()"; }
void boo() { std::cout << "boo()"; }
void too() { std::cout << "too()"; }
void goo() { std::cout << "goo()"; }

int main() {
  std::map<std::string, std::function<void()>> functions;
  functions["foo"] = foo;
  functions["boo"] = boo;
  functions["too"] = too;
  functions["goo"] = goo;

  std::string func;
  std::cin >> func;
  if (functions.find(func) != functions.end()) {
    functions[func]();
  }
  return 0;
}

【讨论】:

  • 函数是一个单独的类吗?请问你能详细说明吗?谢谢
  • function 是 C++11 中的新类,位于 functional 标头中。
  • 非常感谢。我的编译器无法编译行 std::map<:string std::function>> functions;但是当我将其更改为此 map 函数时它会运行;现在可以了。我以前没有使用过 map 并且对函数指针知之甚少。我做了正确的事情还是可以以更好的方式修复它?是否可以使用这种方式传递参数?
  • 为什么不呢?将其传递给呼叫。关于 C++11:在 GCC 中,您必须使用 -std=c++11 标志才能编译和工作。
  • 如果我有void foo(x){std::cout&lt;&lt;x;} 并且我输入了foo(2),我该如何像你上面所说的那样“将它传递给呼叫”?我知道我必须更改地图,但是如何从字符串中提取参数?
【解决方案2】:

至少有两种选择:

  • command pattern.
  • 在 Windows 上,您可以使用 GetProcAddress 按名称获取回调,并在 *nix 上使用 dlopen + dlsym

【讨论】:

  • 你能举个例子吗。
  • @DipeshKc 我相信您可以通过 google 轻松找到一个(两种选择)。
【解决方案3】:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;


double eval( string expression );


int main( int argc, char *argv[] )
{
    string expression = "";
    for ( int i = 1; i < argc; i++ )
    {
       expression = expression + argv[i];
    }
    cout << "Expression [ " << expression << " ] = " << endl;

    eval( expression );
}


double eval( string expression )
{
    string program = "";
    program = program + "#include <cmath>\n";
    program = program + "#include <iostream>\n";
    program = program + "using namespace std;\n";
    program = program + "int main()\n";
    program = program + "{\n";
    program = program + "   cout << ";
    program = program + expression;
    program = program + " << endl;\n";
    program = program + "}";


    ofstream out( "abc.cpp" );
    out << program;
    out.close();

    system( "g++ -o abc.exe abc.cpp" );
    system( "abc" );
}

【讨论】:

  • 编译代码的编译程序。请注意,这并不适用于所有平台。
  • @DavidA 我不明白为什么会这样。我在 swift 中尝试了类似的方法,即使有 10 秒的延迟,由于编译器的工作方式,它会以编译时的方式执行文件。
【解决方案4】:

您可以尝试采用现有的脚本引擎,向它公开您喜欢的函数,然后使用它来评估您的语句。 V8 引擎就是这样一种引擎:https://developers.google.com/v8/intro,但有许多替代方案和不同的语言可供选择。

这里有一些例子:

【讨论】:

    【解决方案5】:

    除了在程序中使用函数映射并在Makefile上破解,您可以通过ELF访问它。

    我认为这种方法更好,因为它不需要编写重复的代码并每次在不同的机器上编译。

    这是我的演示 C/C++ equivalent of eval(“function(arg1, arg2)”)

    #include<stdio.h>
    #include<stdlib.h>
    #include<elf.h>
    #include<libelf.h>
    #include<unistd.h>
    #include<fcntl.h>
    #include<gelf.h>
    #include<string.h>
    
    void my_fun()
    {
        int a = 19;
        printf("my_fun is excute, a is %d \n", a);
    }
    
    void my_fun2()
    {
        printf("my_fun2 is excute\n");
        return;
    }
    
    void my_fun3()
    {
        return;
    }
    
    void excute_fun(char *program_name, char *function_name)
    {
        int i, count;
        Elf32_Ehdr *ehdr;
        GElf_Shdr   shdr;
        Elf *elf;
        Elf_Scn *scn = NULL;
        Elf_Data *data;
        int flag = 0;
        int fd = open(program_name, O_RDONLY);
        if(fd < 0) {
            perror("open\n");
            exit(1);
        }
        if(elf_version(EV_CURRENT) == EV_NONE) {
            perror("elf_version == EV_NONE");
            exit(1);
        }
        elf = elf_begin(fd, ELF_C_READ, (Elf *) NULL);
        if(!elf) {
            perror("elf error\n");
            exit(1);
        }
        /* Elf32_Off e_shoff; */
        /* if ((ehdr = elf32_getehdr(elf)) != 0) { */
        /*     e_shoff = ehdr->e_shoff; */
        /* } */
        /* scn = elf_getscn(elf, 0); */
        /* printf("e_shoff is %u\n", e_shoff); */
        /* scn += e_shoff; */
        while ((scn = elf_nextscn(elf, scn)) != NULL) {
            gelf_getshdr(scn, &shdr);
            if (shdr.sh_type == SHT_SYMTAB) {
                /* found a symbol table. */
                break;
            }
        }
        data = elf_getdata(scn, NULL);
        if(!shdr.sh_entsize)
            count = 0;
        else
            count = shdr.sh_size / shdr.sh_entsize;
        for (i = 0; i < count; ++i) {
            GElf_Sym sym;
            gelf_getsym(data, i, &sym);
            char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
            if(sym_name != NULL && sym_name[0] != '_' && sym_name[0] != '\0' && sym_name[0] != ' ' && sym.st_value != 0)
            {
                /* printf("sym_name is %s\n", sym_name); */
                /* printf("%s = %X\n", elf_strptr(elf, shdr.sh_link, sym.st_name), sym.st_value); */
                if(!strcmp(sym_name, function_name)) {
                    void (*fun)(void) = (void*)sym.st_value;
                    (*fun)();
                    flag = 1;
                }
            }
        }
        if(!flag)
            printf("can not find this function\n");
    
        elf_end(elf);
        close(fd);
    }
    
    int main(int argc, char *argv[])
    {
        char *input = (char*)malloc(100);
        for(;;) {
            printf("input function_name to excute: ");
            scanf("%s", input);
            excute_fun(argv[0], input);
            memset(input, 0, sizeof(input));
            printf("\n");
        }
        free(input);
        return 0;
    }
    

    此实现基于Example of Printing the ELF Symbol Table

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多