Typedef in einer Klasse verwenden



  • Zuerst einmal Hallo an alle,
    hoffe das ich hier ein wenig lernen kann und evtl sogar etwas von meinem Wissen weitergeben kann.

    Leider fängt alles erstmal mit einem Problem an 😕

    Geschichte drum herum:
    Ich möchte für einen LCD-Bildschirm mit hilfe der Logitech LCD SDK ein eigenes Plugin programmieren. Habe schon Erfahnung in PHP, Perl und Java. (Alles sehr System-nahme Sprachen 🙄 )

    Soo. bei dem LCD-Bildschirm sind auch Buttons dabei, welche mit dem SDK angesprochen werden können. Ich möchte eine eigene Callback-Funktion implementieren, um auf die Tastendrücke zu reagieren.

    Die Funktion soll laut TypeDef wie folgt aussehen:

    // Callback used to notify client of soft button change
    typedef DWORD (WINAPI *lgLcdOnSoftButtonsCB)(IN int device, IN DWORD dwButtons, IN const PVOID pContext);
    

    Das ganze Funktioniert auch, wenn ich eine einfache Methode erstelle, welche in keiner Klasse liegt. Also z.b:

    DWORD myCallback(IN int device, IN DWORD dwButtons, IN const PVOID pContext)
    {
    	return 1;	
    }
    

    Da ich das ganze Objekt-Orientiert umsetzen möchte, implementieren ich die Funktion für den Callback wie folgt:
    LCDMain.h

    class CLCDMain
    {
    public:
    DWORD buttonCallback(IN int device, IN DWORD dwButtons, IN const PVOID pContext);
    
    ....
    

    LCDMain.cpp

    CLCDMain::CLCDMain()
    {
    	//Einige Zeilen
    	//Temp-Variable for Button-Callback
    	lgLcdOnSoftButtonsCB myFuncButtonCallback;
    	myFuncButtonCallback = &CLCDMain::buttonCallback;
    
    	openContext.onSoftbuttonsChanged.softbuttonsChangedCallback = myFuncButtonCallback;
    
    }
    //Einige Zeilen
    
    DWORD CLCDMain::buttonCallback(IN int device, IN DWORD dwButtons, const IN PVOID)
    {
    return 1;
    }
    

    Dabei kommt aber leider folgender Fehler:

    1>e:\privat\programmieren\cpp\lcd\lcd\lcdmain.cpp(13) : error C2440: '=': 'DWORD (__thiscall CLCDMain::* )(int,DWORD,const PVOID)' kann nicht in 'lgLcdOnSoftButtonsCB' konvertiert werden
    1>        Es gibt keinen Kontext, in dem diese Konvertierung möglich ist
    

    Ist das ganze zu lösen oder ist dabei eine größere Veränderung in dem SDK nötig?
    Falls das möglich ist, gibts Tipps oder Schlüsselwörter über die ich mich schlau mache kann?
    Danke für jede Hilfe



  • Schau dir mal Zeiger auf klasseninterne Methoden an. Dein typedef ist für Zeiger auf freie Funktionen.

    Wenn du dir Arbeit sparen willst, schau dir std::function oder den entsprechenden Boost-Teil an.



  • Ah. Da hast du dir als erstes Problem gleich hübsch was ausgesucht.

    Das Problem ist der Unterschied zwischen Funktionszeigern und Methodenzeigern. Zum einen haben Methoden einen versteckten Parameter this, der durch den Funktionszeiger nicht erschlagen wird, zum anderen macht die Möglichkeit virtueller Methoden Methodenzeiger zu einer etwas komplexeren Angelegenheit. Es ist dementsprechend nicht möglich, eine Methode in einen Funktionszeiger zu stopfen.

    APIs dieser Art erlauben es aber üblicherweise, einen Kontext mitgeben, der wieder an die Callback-Funktion durchgereicht wird; das wird in deinem Fall wohl pContext sein. Die Lösung deines Problems ist wahrscheinlich, eine Funktion wie folgt zu schreiben:

    DWORD myCallback(IN int device, IN DWORD dwButtons, IN const PVOID pContext)
    {
      CLDCMain *self = reinterpret_cast<CLDCMain*>(pContext);
    
      self->buttonCallback(device, dwButtons);
    }
    

    ...und einen Zeiger auf das Objekt als Kontext mitzugeben, wenn du den Callback registrierst.

    Wenn es sich bei der Callbackerei nicht um eine externe Bibliothek handelt und du das API umstrukturieren kannst, könnte man das mit std::tr1::function im API und std::tr1::bind auf der Client-Seite eleganter lösen, aber die Kiste sieht mehr nach einer alten C-Bibliothek aus, die niemand mit der Kneifzange mehr anfassen will.



  • Danke an beide.

    seldon dein Tipp bzw dein Code hat es gerettet. Es stimmt, der letzte Parameter kann dazu genutzt werden um das Objekt selbst mit an den Handler zu übergeben.
    Also es funktioniert jetzt wie folgt:

    //Im Code:
    openContext.onSoftbuttonsChanged.softbuttonsChangedCallback = myFuncButtonCallback;
    	openContext.onSoftbuttonsChanged.softbuttonsChangedContext = this;
    
    //Wo anders:
    
    DWORD WINAPI myCallback(IN int device, IN DWORD dwButtons, IN const PVOID pContext)
    {
    	CLCDMain *self = reinterpret_cast<CLCDMain*>(pContext);
    	return self->buttonCallback(device, dwButtons);
    } 
    
    DWORD WINAPI CLCDMain::buttonCallback(IN int device, IN DWORD dwButtons)
    {
    	switch(dwButtons)
    	{
    	case 1:
    		printf("Button 1 Pressed\n");
    		break;
    	case 2:
    		printf("Button 2 Pressed\n");
    		break;
    	case 4:
    		printf("Button 3 Pressed\n");
    		break;
    	case 8:
    		printf("Button 4 Pressed\n");
    		break;
    	default:
    		printf("Button Released\n");
    	}
    	return 1;
    }
    

Log in to reply