Events / Memberfunktionen



  • Hallo zusammen,

    ich habe innerhalb einer Klasse eine Methode deklariert:

    private: void _stdcall Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, unsigned long hUser);
    

    Die Adresse der Methode soll an eine Funktion übergeben werden:

    AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, &NotificationSettings, Callback, lHdlVar, &lHdlNotification);
    

    Die Funktion "AdsSyncAddDeviceNotificationReq" kann nicht geändert werden.

    Deklariere ich die Methode innerhalb der Klasse wie oben beschrieben, bekomme ich eine Fehlermeldung:

    [BCC32 Fehler] ********************: E2034 Konvertierung von 'void (__stdcall * (_closure )(AmsAddr *,AdsNotificationHeader *,unsigned long))(AmsAddr *,AdsNotificationHeader *,unsigned long)' nach 'void (__stdcall *)(AmsAddr *,AdsNotificationHeader *,unsigned long)' nicht möglich
    

    Deklariere ich die Methode innerhalb meiner Klasse als statische Methode, kann ich den Quellcode zwar fehlerfrei kompilieren, aber leider nicht mehr auf die Variablen zugreifen, die innerhalb der Klasse deklariert wurden. Soweit verständlich.
    Habt ihr vielleicht einen Tipp für mich, in welche Richtung ich den Fehler bzw. eine Lösung suchen könnte?

    Danke im Voraus!



  • Als static hast du die Funktion schon deklariert, anschließend würde ich mir mal den Parameter hUser von AdsSyncAddDeviceNotificationReq anschauen. Dieser Wert wird unverändert an die Callback-Funktion übergeben.
    Das könnte bspw. die Adresse der Klasse sein, mit deren Hilfe du anschließend eine beliebige Memberfunktion aufrufen könntest.
    Zumindest bei 32 Bit-Anwendungen, wenn ich mir das hier anschaue.
    Bei 64 Bit wäre es eine Sackgasse.



  • Du versuchst der Funktion AdsSyncAddDeviceNotificationReq eine Memberfunktion zu übergeben (beim C++ Builder erkennst du das am Schlüsselwort __closure). Das funktioniert natürlich nicht, da __closure einen unsichtbaren this Pointer in der Signatur versteckt und damit nicht mehr auf void (__stdcall *)(AmsAddr *,AdsNotificationHeader *,unsigned long) passt.
    Wie du schon richtig erkannt hast geht das entweder mit einer statischen Memberfunktion (weil sie keinen this Pointer braucht, weil sie static ist) oder einer freien Funktion. In beiden Fällen hast du tatsächlich keinen Zugriff mehr auf das Objekt, das den Callback eigentlich behandeln soll.

    Dazu gibt´s jetzt zwei Lösungen (C++03 weil du den BCC32 benutzt, der noch kein C++11 beherrscht):

    • oft bietet die API bei Callbacks einen frei definierbaren Parameter, in dem du einen Zeiger auf dein Objekt codieren könntest
    • du brauchst eine globale Variable, auf die du im Callback zugreifen kannst. Die Lösung ist aber eher bäh.


  • @yahendrik sagte in Events / Memberfunktionen:

    Als static hast du die Funktion schon deklariert, anschließend würde ich mir mal den Parameter hUser von AdsSyncAddDeviceNotificationReq anschauen. Dieser Wert wird unverändert an die Callback-Funktion übergeben.
    Das könnte bspw. die Adresse der Klasse sein, mit deren Hilfe du anschließend eine beliebige Memberfunktion aufrufen könntest.
    Zumindest bei 32 Bit-Anwendungen, wenn ich mir das hier anschaue.
    Bei 64 Bit wäre es eine Sackgasse.

    hUser ist die Adresse der Variable, die eine Notification ausgelöst hat und leider nicht in die Adresse der Klasse.



  • @DocShoe Danke für die Antwort. Vielleicht noch etwas dazu, was ich eigentlich machen möchte: über die Callback Funktion soll durch die Klasse ein Event generiert werden, auf dass dann im Programm zugegriffen werden kann. Daher bringt mir die Lösung mit der globalen Variablen nicht wirklich etwas, da ich dann innerhalb der Klasse einen Timer programmieren muss, der diese globale Variable dann ständig abfragt. Oder verstehe ich das falsch?



  • @thar36

    Guckst du hier



  • @DocShoe Danke dir. Das Problem ist auch hier, dass ich nicht auf die Objekte innerhalb der Klasse zugreifen kann, da diese nicht initialisiert sind. ...



  • @thar36

    Wat?



  • @DocShoe Ich gehe mal davon aus, dass ich deine Lösung irgendwie falsch implementiert habe und ich deshalb Probleme beim Zugriff auf die Eigenschaften der Klasse habe.

    Zum Hintergrund:
    Innerhalb der Klasse habe ich ein Register auf welches ich innerhalb der Callback-Routine zugreifen muss. Wenn ich deine Lösung implementiere, ist dieses Register nicht initialisiert, obwohl dort definitiv bereits Daten enthalten sind.

    Daher werde ich jetzt die hier bereits genannte Lösung mit den globalen Variablen verwenden. Die Methoden rund um "ADS" dienen dazu, den Zustand von Variablen aus einem ADS-Server auszulesen und innerhalb der Software abzulegen. Daher sind die dafür notwendigen Variablen sowieso global vorhanden, so dass ich diese Lösung nutzen kann.

    Auch wenn mir das eigentlich missfällt, es funktioniert und läuft damit fehlerfrei.

    Besten Dank noch einmal für deine / eure Hilfe!


Log in to reply