5

Ich habe eine Klasse mit Instanzfunktionen (oder Methoden?). In einer Instanz versuche ich, Zeiger auf diese Funktionen an eine Bibliothek zu übergeben. Die Bibliothek erwartet statische Funktionen.Um einen Zeiger auf eine Elementfunktion übergeben

Wenn ich meine Zeiger auf die Callback-Funktionen übergeben, beschwert sich der Compiler, dass meine Funktionen nicht statisch sind. Ich habe versucht, sie statisch zu machen, aber wenn ich das tue, kann ich nicht auf die Instanzfelder innerhalb der Funktionen zugreifen.

Wie könnte ich das umgehen?

Ähnliche Frage ist: Using a C++ class member function as a C callback function wo sie vorschlagen, die Methode statisch zu setzen. Aber ich kann das nicht, oder ich sehe nicht, wie ich es könnte.

-Code

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 
} 

Haftungsausschluss: I C++ gerade erst begonnen. Ich lese alles von Accelerated C++ und dies ist mein erstes Projekt, um die Sprache auszuprobieren. Mein Hintergrund ist in Java.

Antwort

7

Was Sie versuchen, ist nicht möglich. Das ist eigentlich glut Fehler. diese

Die Sache ist die:

  • glut will eine Funktion aufzurufen, ohne es Daten gibt,
  • Sie möchten Ihre Funktion einige Daten verwenden,

die Bedürfnisse sind widersprüchlich. Ich glaube, glut entschieden, dass Sie sicher globale Variablen verwenden können. Eine Lösung besteht darin, statische Funktionen mit statischen Daten zu verwenden. Oder eine bessere Lösung wäre, auf SDL zu wechseln.

+0

Ich weiß nicht viel über Schwemme, aber es klingt, als ob es etwas aufrufbar erfordert, das keine Argumente (implizit eingeschlossen) braucht. Würde also eine passend konstruierte 'std :: function' nicht funktionieren? – juanchopanza

+2

Wer eine undurchsichtige Bibliotheksfunktion entwickelt, die keine benutzerdefinierten Parameter annehmen kann (z. B. zur Verwendung in Rückrufen), sollte gefeuert, zum Marketing/Verkauf befördert werden oder einen finanziellen Anreiz erhalten, für ein konkurrierendes Unternehmen zu arbeiten. –

+0

@Shahbaz Ich versuche, eine einfache Demo zu machen, und ich habe gelesen, dass diese Flut sehr einfach im Vergleich zu SDL in Bezug auf Boilerplate Code zu verwenden war. Außerdem verwende ich das Buch "OpenGL SuperBible", um mich zu führen. Ich denke, mit statischen/globalen wird unvermeidlich sein, oder verwenden Sie ein Singleton wie Nick in seiner Antwort unten sagte. – AntoineG

1

sollten Sie eine static method haben und eine instance (möglicherweise statisch) eine Elementfunktion von instance von static Funktion wie diese

Etwas zu nennen:

//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

Kurz gesagt, man kann es nicht. C++ - Memberfunktionen sind tatsächlich mit der Instanz des Objekts verknüpft. Auf der unteren Ebene haben sie einen zusätzlichen Parameter, der eigentlich der Zeiger auf die Instanz dieses Objekts ist.

Also, Sie müssen statische Funktion verwenden, und da Überschwang Sie nicht übergeben würde, einen Parameter, der die aktuelle Instanz identifizieren würde, müssen Sie mit einer Workaround kommen. Die einfachste Problemumgehung wäre die Verwendung statischer Member. Wenn dein GlutController Singleton ist (und ich denke es ist), wird es dir gut gehen.

2

Es ist möglich und scheinbar sicher, eine statische Dateivariable zu verwenden, die auf Ihre GlutInstance verweist (statische Funktion + statische Daten, wie in einer anderen Antwort erwähnt).

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 ist nur sichtbar in der lokalen Datei, z.B. Nicht sichtbar für Code, der den GlutController-Konstruktor aus einer anderen Datei aufruft.