2012-06-18 22 views
16

nó cần một cách để gọi hàm có tên được lưu trữ trong một chuỗi tương tự như eval. Bạn có thể giúp?Có tương đương C/C++ của eval ("hàm (arg1, arg2)") không?

+2

Nope, đặt cược tốt nhất của bạn là mô hình lệnh. – AraK

+0

Nếu bạn sẵn sàng cúi đầu trước sức mạnh của qt, có: http://qt-project.org/doc/qt-4.8/QMetaObject.html – fritzone

+1

Có một số phiên dịch C++: http://stackoverflow.com/questions/69539/have-you-used-bất kỳ-of-the-c-interpreters-not-compilers/ –

Trả lời

16

C++ không có phản ánh để bạn phải hack nó, i. 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; 
} 
+0

là một lớp học riêng biệt? Xin bạn có thể xây dựng? Cảm ơn –

+0

'function' là lớp mới trong C++ 11 trong tiêu đề' functional'. – Hauleth

+0

Cảm ơn rất nhiều. Trình biên dịch của tôi không thể biên dịch các dòng std :: map > functions; Nhưng nó chạy khi tôi thay đổi nó thành các hàm bản đồ này; Nó hoạt dộng bây giờ. Tôi đã không sử dụng bản đồ trước và biết rất ít về các con trỏ chức năng. Tôi đã làm đúng hay có thể sửa nó một cách tốt hơn?Có thể truyền tham số bằng cách này không? –

8

Có ít nhất 2 lựa chọn:

  • Các command pattern.
  • Trên cửa sổ, bạn có thể sử dụng GetProcAddress để gọi lại theo tên và dlopen + dlsym trên * nix.
+0

bạn có thể cho một ví dụ hay không. –

+5

@DipeshKc Tôi chắc chắn bạn có thể dễ dàng tìm thấy một (cho cả hai lựa chọn thay thế) với google. –

2

Bạn có thể thử áp dụng công cụ tạo tập lệnh hiện có, hiển thị các chức năng bạn thích và sau đó sử dụng hàm này để đánh giá các câu lệnh của bạn. Một động cơ như vậy có thể là động cơ V8: https://developers.google.com/v8/intro nhưng có nhiều lựa chọn thay thế và các ngôn ngữ khác nhau để bạn lựa chọn.

Dưới đây là một số ví dụ:

2

Trừ bằng cách sử dụng bản đồ chức năng trong chương trình và hack nó trên Makefile, bạn có thể truy cập thông qua E LF.

Tôi nghĩ rằng phương pháp này là tốt hơn vì nó không cần phải viết mã trùng lặp và biên dịch nó mỗi lần trên máy khác nhau.

Dưới đây là bản demo của tôi 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; 
} 

thực hiện này được dựa trên Example of Printing the ELF Symbol Table

2
#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"); 
} 
+1

Một chương trình biên dịch biên dịch mã. Nên lưu ý rằng điều này không hoạt động trên tất cả các nền tảng. – Mossarelli

Các vấn đề liên quan