PDA

Visualizza la versione completa : [C++] Passaggio di callback da una classe


zaxis
21-12-2005, 09:11
Sto continuando a fare esperimenti, stavolta con qualcosa di piu' costruttivo. Ho scaricato un codice d'esempio banale, che funziona con le openGL, ed ho provato a farci una classe. Ovviamente non funziona...
In particolare il codice funzionante definisce alcune funzioni, tipo

void display ( void )
void reshape(int w, int h)
void keyboard ( unsigned char key, int x, int y )

e poi le passa ad una funzione delle glut, in questo modo:

glutReshapeFunc ( reshape );
glutKeyboardFunc ( keyboard );
glutDisplayFunc ( display );

Io ho provato a fare una classe, e poi passare i suoi metodi esattamente allo stesso modo:

glutReshapeFunc ( MHgui.reshape );
glutKeyboardFunc ( MHgui.keyboard );
glutDisplayFunc ( MHgui.display );

Ma il compilatore mi restituisce un errore tipo:

error: argument of type `void (MHwindow::)(int, int)' does not match `void (*)(int, int)'
error: argument of type `void (MHwindow::)(unsigned char, int, int)' does not match `void (*)(unsigned char, int, int)'
argument of type `void (MHwindow::)()' does not match `void (*)()'

Per favore, datemi una mano!


qui sotto vi allego un link al codice che funziona e il listato di quello che non funziona...

Codice che funziona:

http://paulyg.f2s.com/prog1.htm

Codice che non funziona:






#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>


class MHwindow
{
private:
int width;
int height;
//*char title;
public:
int getWidth();
int getHeight();
void init();
void display();
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);
} ;

int MHwindow::getWidth(){return width;}
int MHwindow::getHeight(){return height;}





void MHwindow::display()
{
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix ( );
glPopMatrix ( );
glutSwapBuffers ( );
}

void MHwindow::reshape(int w, int h)
{
glViewport ( 0, 0, w, h );
glMatrixMode ( GL_PROJECTION );
glLoadIdentity ( );
if ( h==0 )
gluPerspective ( 80, ( float ) w, 1.0, 5000.0 );
else
gluPerspective ( 80, ( float ) w / ( float ) h, 1.0, 5000.0 );
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity ( );

}

void MHwindow::keyboard ( unsigned char key, int x, int y )
{
switch ( key ) {
case 27: /* Escape key */
exit ( 0 );
break;
case 'f':
glutFullScreen ( );
break;
case 'w':
glutReshapeWindow ( 100,100 );
break;
default:
break;
}
}

/* Main Loop
* Open window with initial window size, title bar,
* RGBA display mode, and handle input events.
*/


MHwindow MHgui;

int main ( int argc, char** argv )
{

glutInit ( &argc, argv );
glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE );
glutInitWindowSize ( MHgui.getWidth(),MHgui.getHeight() );
glutCreateWindow ( "pippo" );
glEnable ( GL_DEPTH_TEST );
glClearColor ( 0.0, 0.0, 0.0, 0.0 );
glutReshapeFunc ( MHgui.reshape );
glutKeyboardFunc ( MHgui.keyboard );
glutDisplayFunc ( MHgui.display );
glutMainLoop ( );
return 0;
}

pprllo
21-12-2005, 10:23
A quanto ne so non si possono passare ad una funzione, attraverso puntatori a funzione "generici", le funzioni membro non statiche di una classe.

zaxis
21-12-2005, 10:48
Dovrei quindi renderle statiche?
(vado a vedere che significa "funzione statica")

newbie
21-12-2005, 12:50
Il tuo è uno di quei problemi che fanno mangiare il cervello a tanta di quella gente... soprattutto nell'ambiente .NET in cui i puntatori a funzione sono stati aboliti dalla faccia della terra!

Comunque la pensata è ottima: la soluzione più gettonata è proprio quella di passare puntatori static. Il casino inizia se devi passare puntatori a metodi non static come tentavi di fare...

Buona fortuna!

zaxis
21-12-2005, 14:05
E' un vero macello:

http://www.parashift.com/c++-faq-lite/pointers-to-members.html

Quindi non c'e' un modo semplice per incapsulare le funzioni glut...?

Avete qualche idea? Volevo creare una semplice libreria che disegnasse entità basilari (tipo rettangoli).
Potrebbe essere la base per un qualcosa di vermante utile...potete aiutarmi?

Ciao!

zaxis
21-12-2005, 16:52
Dunque...questa qui sembra essere compilabile.
Ma ovviamente la dichiarazione dei membri static la rende tutt'altro che una libreria...
In particolare la funzione display e quella della keyborad non puo' essere static...




#include <windows.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>


class MHwindow
{
private:
int width;
int height;
//*char title;
public:
MHwindow(int, int);
int getWidth();
int getHeight();
static void init();
static void display();
static void reshape(int, int);
static void keyboard(unsigned char, int, int);
} ;


int MHwindow::getWidth(){return width;}
int MHwindow::getHeight(){return height;}
MHwindow::MHwindow(int w, int h)
{
width = w;
height = h;
}

void MHwindow::display()
{
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix ( );
glPopMatrix ( );
glutSwapBuffers ( );
}

void MHwindow::reshape(int w, int h)
{
glViewport ( 0, 0, w, h );
glMatrixMode ( GL_PROJECTION );
glLoadIdentity ( );
if ( h==0 )
gluPerspective ( 80, ( float ) w, 1.0, 5000.0 );
else
gluPerspective ( 80, ( float ) w / ( float ) h, 1.0, 5000.0 );
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity ( );

}

void MHwindow::keyboard ( unsigned char key, int x, int y )
{
switch ( key ) {
case 27: /* Escape key */
exit ( 0 );
break;
case 'f':
glutFullScreen ( );
break;
case 'w':
glutReshapeWindow ( 100,100 );
break;
default:
break;
}
}

/* Main Loop
* Open window with initial window size, title bar,
* RGBA display mode, and handle input events.
*/


MHwindow MHgui(100,100);

int main ( int argc, char** argv )
{

glutInit ( &argc, argv );
glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE );
glutInitWindowSize ( MHgui.getWidth(),MHgui.getHeight() );
glutCreateWindow ( "pippo" );
glEnable ( GL_DEPTH_TEST );
glClearColor ( 0.0, 0.0, 0.0, 0.0 );
glutReshapeFunc ( MHgui.reshape );
glutKeyboardFunc ( MHgui.keyboard );
glutDisplayFunc ( MHgui.display );
glutMainLoop ( );
return 0;
}

DydBoy
21-12-2005, 20:26
Il fatto è che stai utilizzando due frameworks diversi.

L'architettura a classi è ottima per la programmazione in OpenGl, ok.

Ma tu utilizzi le chiamate glutXXX (che funziona a callbacks) della libreria Glut.h che sono state progettate per un utilizzo "C-Style".

Ti consiglio di impararti il minimo che c'è da sapere sulle API di Windows e rimettere su il tutto così come stai implementando.

Il sito di Nehe è una bibbia per questo :

http://nehe.gamedev.net/

Si tratta semplicemente di evitare chiamate come glutInitWindow, glutMainWindow e robe del genere e sostituirlo con il sistema di creazione finestre e smistamento eventi base del sistema operativo Microsoft.

zaxis
21-12-2005, 21:09
Ci sono altre librerie che usano (mooooolto meglio della schifezza che ho scarabbocchiato io) le glut (o le SDL) con questa idea di integrarle in una lib piu' semplice (PUI, BSGUI, etc...).

Il problema e' uno solo: la necessita' del multipiattaforma...

Volevo tentare di scrivere un qualcosa in prima persona per capire meglio come sono state affrontati i problemi dagli altri.

Programmare solo per win non sarebbe un problema, con il VC++ express (gratuito) si costruiscono le GUI in un attimo...

Per questo pensavo di sfruttare in qualche modo le glut, ma in effetti non e' facilissimo.

Pensando al multipiattaforma...qualche idea??

Ciao,

Zax

Loading