2012-01-19 29 views
8

Aparte de impulsar (función Bind &), ¿cómo puedo invocar dinámicamente una función en C++?cómo invocar dinámicamente una función en C++

PHP tiene:

$obj = new MyObject(); 
$function = 'doSomething'; 
$obj->$function(); 

de Objective-C tiene:

MyObject *obj = [[MyObject alloc] init]; 
SEL function = NSSelectorFromString(@"doSomething"); 
[obj performSelector: function]; 
+0

http://stackoverflow.com/questions/11016078/is-it-possible -to-create-a-function-dynamically-during-runtime-in-c – dtech

+0

Palabras clave de búsqueda relacionadas: en C++ buscar "funciones virtuales" y "vinculación tardía o vinculación dinámica". En C "puntero a funciones". – lepe

Respuesta

2

Si aquellas funciones que le interesan son de mismo tipo, se podría crear un mapa de cadenas y punteros de función.

+0

Eso significa que necesito mantener la lista actualizada. Estoy buscando más automático. – joels

+0

Puede usar algún programa para generarlo (tal vez incluso ctags con un poco de sed al final) – stralep

+0

@joels - la generación de código es fácil. – dtech

2

La respuesta simple es que no se puede. C++ no hace que el método busque por nombre.

+1

Incorrecto, puede buscar funciones DLL por nombre. – dtech

+2

@Ddriver DLL no son parte de C++, y las funciones de DLL no son métodos de C++. – Roddy

+0

@Roddy: puede compilar C++ a DLL y obtener un puntero a la función mediante una búsqueda de nombre. DLL en Windows, así que en Linux, lo que sea, PUEDE buscar funciones en bibliotecas dinámicas por nombre, eso es un hecho. – dtech

8

Puede exportar las funciones necesarias (por ejemplo, marcándolas con __dllexport) y utilizar GetProcAddress o dlsym (dependiendo de la plataforma) para conseguir su dirección:

 

void *handle = dlsym(0, RTLD_LOCAL | RTLD_LAZY); 
FunctionType *fptr = (FunctionType *)dlsym(handle, "doSomething"); 
fptr(); 
 
 

HANDLE handle = GetCurrentProcess(); 
FunctionType *fptr = (FunctionType *)GetProcAddress(handle, "doSomething"); 
fptr(); 
 

Todo esto es específico de la plataforma sin embargo, no hay una forma estándar en C++ para hacer esto.

+3

No me puedo quejar, esa es una buena respuesta.Sin embargo, señalaré que es excelente para llamadas dinámicas a funciones C y que no va a funcionar para llamadas polimórficas de métodos C++. –

+0

@GrahamPerks: bueno, será aún más específico de la plataforma con cosas tales como modificar, ajustar punteros a objetos y cosas similares, pero no del todo imposibles. Aunque, dudo que alguna vez lo haga en el entorno de producción. –

+1

También puede marcar las funciones a las que desea hacer referencia con extern "C" en la declaración para evitar que los nombres se arruinen durante la compilación. extern "C" void hello() { std :: cout << "Hola \ n"; } Esto le permitirá llamar a su función por el nombre. void * handle = dlsym (0, RTLD_LOCAL | RTLD_LAZY); FunctionType * fptr = (FunctionType *) dlsym (handle, "hello"); fptr(); Esto es lo que hace el extern "C" bajo el capó: http://stackoverflow.com/questions/1041866/inc-c-source-what-is-the-effect-of-extern-c – deadbabykitten

2

Si entendí bien su pregunta, puede utilizar el puntero de función (o puntero al miembro) en C++. Puede decidir dinámicamente qué función invocar (puede necesitar un prototipo de la misma) y llamarla dinámicamente. Vea este enlace

https://isocpp.org/wiki/faq/pointers-to-members

2

Ampliando la respuesta de Konstantin Oznobihin a la pregunta, puede marcar las ++ funciones de C está haciendo referencia con extern "C" en la declaración para evitar que el compilador de mangling los nombres durante la compilación.

extern "C" void hello() { 
    std::cout << "Hello\n"; 
} 

Esto le permitirá llamar su objeto/función por el nombre que inicialmente le dio. En este caso, es 'hola'.

void *handle = dlsym(0, RTLD_LOCAL | RTLD_LAZY); 
FunctionType *fptr = (FunctionType *)dlsym(handle, "hello"); 
fptr(); 

Hay un montón de cosas extern "C" hace bajo el capó, así que aquí está una lista corta: In C++ source, what is the effect of extern "C"?

+0

Edita y edita agrega esto a la respuesta de @KonstantinOznobihin. De todos modos, gracias por un buen consejo. – Jet

Cuestiones relacionadas