Cómo ejecutar una función si sé su dirección

No está claro si desea una respuesta C o una respuesta C ++, usaré C ya que ahí es donde primero se agregó la pregunta (C ++ es lo suficientemente similar):

Suponiendo que la dirección de la función se almacena en un puntero tipeado adecuadamente, solo use la expresión de llamada de función. Si no está almacenado en un puntero con el tipo apropiado, primero emite y luego llama:

  #include 
 #include 
 #include 

 int fun (int x) {return x + 2;  }

 int main (nulo)
 {
     int (* fptr) (int) = diversión;  // la dirección se almacena aquí
     intptr_t x = (intptr_t) fptr;  // su forma entera aquí

     printf ("La dirección es% p (como puntero)"
            "o% #" PRIxPTR "(como entero) \ n", fptr, x);

     // ahora llámalos
     printf ("Llamando a través de ptr:% d, a través de int:% d \ n",
            fptr (9), ((int (*) (int)) x) (8));
 }

demostración en vivo: Coliru Viewer

Esto es exactamente lo que se hace durante la carga dinámica de bibliotecas. Usted hace la carga, luego obtiene la dirección de una función por nombre. Luego convierte la dirección a una variable de tipo de puntero de función correcta y la llama.

Técnicamente, no es apropiado emitir un puntero a datos (el vacío *) desde la búsqueda de símbolos a un puntero de función, y a menudo recibirá advertencias sobre “conversión no portátil”, pero C le permitirá hacerlo.

Hay una forma portátil correcta de hacerlo que no se usa mucho: haga que la búsqueda sea para un objeto de datos que contenga punteros a funciones en la biblioteca cargada. Aquí hay un ejemplo de UNIX / LINUX:

  #include 
 #include 

 // estos realmente deberían estar en un 
 typedef struct modcx modcx;

 typedef modcx * (* modinitf) (nulo);
 typedef int (* modworkf) (modcx * cx, ...);
 typedef void (* modtermf) (modcx * cx);

 estructura typedef
 {
   modinitf initf;
   modworkf workf;
   modtermf termf;

 } moddesc;


 int usemodule (const char * modname, const char * descname)
 {
   vacío * modhandle = NULL;
   moddesc * mod = NULL;
   modcx * modcx = NULL;
   int rv = 1;    
  
   if (! (modhandle = dlopen (modname, RTLD_LAZY)))
     ir a terminar;

   if (! (mod = dlsym (modhandle, descname)))
     ir a terminar;

   if (! (modcx = mod-> initf ()))
     ir a terminar;

   rv = mod-> workf (modcx,
                    "op", "conquista el mundo",
                    "hora de inicio", "puesta de sol"
                    "tiempo de espera", "12h",
                    "agente", "meñique",
                    "agente", "cerebro",
                    NULO );

  terminar:
  
   si (modcx)
     mod-> workf (modcx);

   if (modhandle)
     dlclose (modhandle);

   volver rv;
 }

Lo mismo en Windows, usando LoadLibrary, GetProcAddress y FreeLibrary.