5

Mam klasę z funkcjami instancji (lub metodami?). Wewnątrz instancji próbuję przekazać wskaźniki do tych funkcji do biblioteki. Biblioteka oczekuje funkcji statycznych.Aby przekazać wskaźnik do funkcji składowej

Kiedy przekazuję moje wskaźniki do funkcji wywołania zwrotnego, kompilator narzeka, że ​​moje funkcje nie są statyczne. Próbowałem ustawić je jako statyczne, ale jeśli to zrobię, nie będę mógł uzyskać dostępu do pól instancji z poziomu funkcji.

Jak mogę to obejść?

Podobne pytanie brzmi: Using a C++ class member function as a C callback function gdzie sugerują, aby umieścić metodę statyczną. Jednak nie mogę tego zrobić, lub nie widzę, jak mogłem.

Kod

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 
} 

Zastrzeżenie: Właśnie rozpoczęła C++. Czytałem wszystkie Accelerated C++ i jest to mój pierwszy projekt wypróbowania języka. Moje doświadczenie jest w Javie.

Odpowiedz

7

To, co próbujesz zrobić, nie jest możliwe. To jest w rzeczywistości błąd glut.

Rzecz jest taka:

  • glut chce wywołać funkcję, nie dając mu dane,
  • Chcesz swoją funkcję do korzystania z niektórych danych,

które są sprzeczne potrzeby. Wierzę, że glut zdecydował, że możesz bezpiecznie używać zmiennych globalnych.

Jednym z rozwiązań jest użycie funkcji statycznych, z danymi statycznymi. Lub lepszym rozwiązaniem byłoby przejście na SDL.

+0

Nie wiem zbyt wiele o obojętności, ale wygląda na to, że wymaga czegoś, co można wywołać, nie ma żadnych argumentów (w tym ukrytych). Więc czy odpowiednio skonstruowana funkcja 'std :: function 'nie poradzi sobie? – juanchopanza

+2

Każdy, kto opracuje nieprzejrzystą funkcję biblioteczną, która nie może przyjąć parametru zdefiniowanego przez użytkownika (np. Do wykorzystania w oddzwanianiach), powinien zostać zwolniony, promowany do marketingu/sprzedaży lub mieć motywację finansową do pracy dla konkurencyjnej firmy. –

+0

@Shahbaz Próbuję zrobić proste demo i przeczytałem, że nadmiar jest bardzo prosty w użyciu w porównaniu do SDL w odniesieniu do kodu standardowego. Używam także książki "OpenGL SuperBible", aby mnie prowadzić. Myślę, że używanie statycznego/globalnego będzie nieuniknione, lub użyj Singleton, jak Nick powiedział w swojej odpowiedzi poniżej. – AntoineG

1

trzeba mieć static method i instance (ewentualnie statyczny) w celu wywołania funkcji składowej instance z static funkcji

coś takiego:

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

Krótko mówiąc, nie można. Funkcje składowe C++ są w rzeczywistości "połączone" z wystąpieniem obiektu. Na niższym poziomie mają jeden dodatkowy parametr, który jest właściwie wskaźnikiem do instancji tego obiektu.

Musisz więc użyć funkcji statycznej, a ponieważ glut nie pozwoliłby ci przekazać parametru identyfikującego bieżącą instancję, będziesz musiał wymyślić jakiś sposób obejścia tego problemu. Najprostszym obejściem byłoby użycie statycznych elementów. Jeśli twój GlutController jest singleton (i myślę, że tak), wszystko będzie dobrze.

2

Jest możliwe i najwyraźniej bezpieczne używanie zmiennej statycznej o zasięgu pliku wskazującej na GlutInstance (funkcja statyczna + dane statyczne, jak wspomniano w innej odpowiedzi).

s_this jest widoczny tylko w pliku lokalnym, np. niewidoczny dla żadnego kodu, który wywołuje konstruktor GlutController z innego pliku.