5

Tengo una clase con funciones de instancia (¿o métodos?). Desde dentro de una instancia, trato de pasar punteros a esas funciones a una biblioteca. La biblioteca espera funciones estáticas.Para pasar un puntero a una función miembro

Cuando paso mis punteros a las funciones de devolución de llamada, el compilador se queja de que mis funciones no son estáticas. Traté de ponerlos estáticos, pero si lo hago, entonces no puedo acceder a los campos de instancia desde dentro de las funciones.

¿Cómo podría solucionar esto?

Pregunta similar es: Using a C++ class member function as a C callback function donde sugieren poner el método estático. Sin embargo, no puedo hacer eso, o no veo cómo podría hacerlo.

Código

GlutController::GlutController (int argc, char **argv) { 

    // stuff .. 

    // Register callbacks 
    glutSpecialFunc(OnSpecialKeys); // Error, need static functions 
    glutReshapeFunc(OnChangeSize); // Error... 
    glutDisplayFunc(OnRenderScene); // Error... 

    // stuff .. 
} 

GlutController::~GlutController() { 

} 

void GlutController::OnChangeSize(int aNewWidth, int aNewHeight){ 

    glViewport(0,0,aNewWidth, aNewHeight); 
    mViewFrustrum.SetPerspective(APP_CAMERA_FOV,    // If this function is 
      float(aNewWidth)/float(aNewHeight),  // static, this won't 
      APP_CAMERA_NEAR,         // work 
      APP_CAMERA_FAR); 
    mProjectionMatrixStack.LoadMatrix(      // Same here 
      mViewFrustrum.GetProjectionMatrix()); 
    mTransformPipeline.SetMatrixStacks(mModelViewMatrixStack, // Same here 
      mProjectionMatrixStack); 

} 

void GlutController::OnRenderScene(void){ 
    mGeometryContainer.draw();        // Won't work if static 
} 

void GlutController::OnSpecialKeys(int key, int x, int y){ 
    mGeometryContainer.updateKeys(key);      // Won't work if static 
} 

responsabilidad: Me acaba de empezar C++. Leí todo Accelerated C++ y este es mi primer proyecto para probar el idioma. Mi experiencia es en Java.

Respuesta

7

Lo que estás tratando de hacer no es posible. Esto es realmente culpa de glut.

La cosa es la siguiente:

  • glut quiere llamar a una función, sin darle datos,
  • usted quiere que su función para utilizar algunos datos,

que están en conflicto necesidades. Creo que glut decidió que puede usar variables globales de forma segura.

Entonces, una solución es usar funciones estáticas, con datos estáticos. O una mejor solución sería cambiar a SDL.

+0

No sé mucho sobre exceso, pero parece que requiere algo invocable, que no toma ningún argumento (incluidos los implícitos). Entonces, ¿no funcionaría una 'std :: function' adecuadamente construida? – juanchopanza

+2

Cualquiera que desarrolle una función de biblioteca opaca que no puede tomar un parámetro definido por el usuario (por ejemplo, para usar en devoluciones de llamada), debe ser despedido, promovido a marketing/ventas o recibir un incentivo financiero para trabajar para una compañía rival. –

+0

@Shahbaz Estoy tratando de hacer una demostración simple, y leí que el exceso era muy simple de usar en comparación con SDL en términos de código repetitivo. También estoy usando el libro 'OpenGL SuperBible' para guiarme. Creo que usar static/global será inevitable, o usar un Singleton como Nick dijo en su respuesta a continuación. – AntoineG

1

usted debe tener una static method y un instance (posiblemente estática) para llamar a una función miembro de instance de static función

Algo como esto:

//static method 
void MyClass::myCallback() 
{ 
    static MyClass instance; //or you can store your in instance in some Singleton, or 
    //possibly create a temporary 
    instance.nonStaticMethod(); 
} 
3

En resumen, no se puede. Las funciones de miembros de C++ en realidad están 'vinculadas' a la instancia del objeto. En el nivel inferior, tienen un parámetro adicional, que en realidad es el puntero a la instancia de este objeto.

Por lo tanto, debe utilizar la función estática, y, como el exceso no le permite pasar un parámetro que identificaría la instancia actual, tendrá que encontrar alguna solución alternativa. La solución más simple sería usar miembros estáticos. Si tu GlutController es singleton (y creo que lo es), estarás bien.

2

Es posible y aparentemente seguro usar una variable estática de archivo que apunta a su GlutInstance (función estática + datos estáticos, como se menciona en otra respuesta).

static GlutController* s_this; 

static void s_OnChangeSize(int w, int h) { s_this->OnChangeSize(w, h); } 

GlutController::GlutController (int argc, char **argv) { 
    s_this = this; 

    glutSpecialFunc(s_OnSpecialKeys); 
} 

GlutController::~GlutController() { s_this= 0; } 

void GlutController::OnChangeSize(int w, int h) { /* non-static stuff */ } 

s_this sólo es visible en el archivo local, por ejemplo, no visible para ningún código que invoca el constructor GlutController desde otro archivo.

Cuestiones relacionadas