2012-06-18 54 views
16

necesita una forma de llamar a la función cuyo nombre está almacenado en una cadena similar a eval. ¿Puede usted ayudar?¿Hay un equivalente C/C++ de eval ("function (arg1, arg2)")?

+2

No, lo mejor es el patrón de comandos. – AraK

+0

Si está dispuesto a ceder ante el poder de qt, sí: http://qt-project.org/doc/qt-4.8/QMetaObject.html – fritzone

+1

Hay algunos intérpretes de C++: http://stackoverflow.com/questions/69539/has-you-used-any-of-the-c-intérpretes-no-compiladores/ –

Respuesta

16

C++ no tiene reflejo así que debe hackearlo, 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

es funcional una clase separada? Por favor, ¿puedes dar más detalles? Gracias –

+0

'function' es una nueva clase en C++ 11 que está en el encabezado' functional'. – Hauleth

+0

Muchas gracias. Mi compilador no pudo compilar las funciones line std :: map >; Pero se ejecuta cuando lo cambio a este mapa funciones; Ahora funciona. No he utilizado el mapa anteriormente y sé muy poco sobre los indicadores funcionales. ¿He hecho lo correcto o podría arreglarlo de una mejor manera?¿Es posible pasar parámetros usando esta forma? –

8

Hay al menos 2 alternativas:

  • El command pattern.
  • En Windows, puede usar GetProcAddress para obtener una devolución de llamada por su nombre, y dlopen + dlsym en * nix.
+0

puede dar un ejemplo, por favor. –

+5

@DipeshKc Estoy seguro de que puede encontrar fácilmente uno (para ambas alternativas) con google. –

2

Se podría tratar de adoptar un motor de secuencias de comandos existentes, exponer las funciones que le gustan a este y luego usar esto para evaluar sus declaraciones. Uno de estos enging podría ser el motor V8: https://developers.google.com/v8/intro, pero hay muchas alternativas y diferentes idiomas para elegir.

Éstos son algunos ejemplos:

2

excepto que se utilizó el mapa de funciones en el programa y entrar ilegalmente en él en el Makefile, se puede acceder a través de E LF.

Creo que este método es mejor, ya que no necesitaba escribir código duplicado y compilarlo cada vez en una máquina diferente.

Aquí es mi demo 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; 
} 

Esta aplicación se basa en 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

Un programa compilado que compila código. Debería tener en cuenta que esto no funciona en todas las plataformas. – Mossarelli