Event wird nicht gefeuert

  • C++

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von Chrisber.

    Event wird nicht gefeuert

    Schönen Nachmittag,
    ich hab eine Klasse Namens "GButton" die erbt von "GControl". GButton wrappt einen Button um ihn einfach zu instanzieren zu können. Jetzt hab ich ein Event

    C-Quellcode

    1. typedef void (*GEventHandler) (void* sender, GEventArgs e);
    2. GEventHandler ButtonClick;

    das public in der Klasse ist. Wenn ich ihm in der Anwendung jetzt einen Wert zuweise, bleibt das Event = NULL. Diesen Eventhandler verwende ich in 2 anderen Klassen ca 70 mal und da klappt es immer. Ich habe keine Ahnung wieso ich dem Event keinen Wert zuweisen kann. Hättet ihr vielleicht eine Idee ?

    Grüße Gonger
    Wenn du dabei Hilfe möchtest, musst du schon mehr Code zeigen. Das was dort zu sehen ist "sollte" klappen. Besonders wenn du das wo anders erfolgreich einsetzt.
    Normalerweise nutzt man für Callbacks ("Events") moderne C++ Funktionen wie std::bind, boost::bind, eine Delegate Implementation oder noch besser Callbacks über Interfaces. Vorteile liegen auf der Hand: kein rumgecaste, keine Pointerfrickelei, kein void*-Abusing, Bindung auf nicht-statische Methoden möglich.
    Das was du da fabrizierst ist nichts anderes als C-Code mit "++" hinten dran.
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    Dann ist bei deiner Problemklasse offensichtlich was falsch, was damit nichts zu tun hat.
    Schreibe uns einen Code-Ausschnitt, der kompilierbar ist. Möglichkeit zwei: zeige uns alle Unterschiede zu den Klassen auf, die sonst funktionieren (minimales kompilierbares Beispiel).
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    GCL_API ist definiert als dllexport/import.

    C-Quellcode

    1. // Der Header
    2. class GCL_API GButton : public GControl
    3. {
    4. public:
    5. GButton(void);
    6. ~GButton(void);
    7. function<void(Object, GEventArgs)> ButtonClick;
    8. protected:
    9. LRESULT WndSubProcMem(HWND hWndw, UINT Msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
    10. };
    11. // und Klasse
    12. GButton::GButton(void)
    13. {
    14. SetClassname(L"Button");
    15. SetText(L"GButton");
    16. ButtonClick = NULL;
    17. }
    18. GButton::~GButton(void)
    19. {
    20. }
    21. LRESULT GButton::WndSubProcMem(HWND hWndw, UINT Msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
    22. {
    23. if(Msg == WM_COMMAND)
    24. {
    25. if(HIWORD(wParam) == BN_CLICKED)
    26. {
    27. if(ButtonClick)ButtonClick(this, GEventArgs());
    28. }
    29. }
    30. return GControl::WndSubProcMem(hWndw,Msg,wParam,lParam,uIdSubclass, dwRefData);
    31. }


    Die Basisklasse ist natürlich umso größer, aber dort funktionieren die CallBacks. Wenn ich jetzt versuche den ButtonClick zu binden gehts schief. Um das ganze zu testen müst ich vielleicht das komplette Projekt hochladen :S
    Das Seltsame ist, zum Aufbau der Basisklasse gibt es keine Unterschiede
    @Chrisber
    Dort geht nichts schief, wenn ich die Instanz erstelle und dann ButtonClick binden will, kommt AccessViolation. Als ich das noch in C-Style hatte, ist einfach garnichts passiert und ButtonClick war immernoch = NULL. Es scheint als könnt ich die Variable nur innerhalb der Klasse ändern obwohl sie public ist
    Ohne kompilierbares Beispiel kann ich nicht helfen. Es muss einen Unterschied geben. Oder du schreibst in geschützten Speicher oder sonst was.

    Gruß
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    Ich versuch grade das auf Events umzustellen (msdn.microsoft.com/en-us/library/ee2k0a7d.aspx) und guck obs damit klappt. Eigentlich kann ich ja nur in geschützten Speicher schreiben laut der Fehlermeldungen, darf bei public aber eig. net sein. Wenns damit nicht klappt lade ich mal die gesamte dll hoch inkl. eines Anwendungsbeispiel in dem der Fehler auftritt.

    Grüße zurück
    Eig. garnix, aber die Variable kann nicht in geschütztem Speicher liegen (oder ich versteh nicht wieso). Das istne normale Klasse mit einer öffentlichen Variable.

    /Edit
    Soo ich habs jetzt auf __event umgestellt und ich glaub ich hab den Übeltäter gefunden. Ich hatte 2 Member vom Typus wstring, diese scheinen es versursacht zu haben. Habs zu nem shared_ptr<wstring> geändert, jetzt läufts ^^ (noch). Falls ähnliche Probleme wieder auftreten meld ich mich nochmal.

    Soweit erstmal ein Dankeschön an @Chrisber

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Gonger96“ ()

    @Gonger96: Ich wette darauf, dass sich das Problem nicht gelöst, sondern nur verschoben hat. Irgendwo schreibst du in geschützten Speicher; es war bloß immer Zufall, dass du es da bemerkt hast.
    std::wstring in einen Smartpointer zu packen ist so sinnlos wie ein Auto ohne Reifen - es bringt nichts.

    Noch was: dieser Event-Kram von Microsoft mag zwar schön sein, ist aber kein Standard C++ und sollte somit vermieden werden.
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Chrisber“ ()

    Hmpf es liegt ganz sicher an den wstrings, ich hab sämtliche Variablen und Funktionen durchgetestet & auskommentiert, erst beim wstring hats aufmal geklappt. Ich probier mal eben obs ohne das __event auskommt und ersetz es mal durchn normalen Pointer.

    /Edit
    Jop es klappt mitm C-Callback auch. Ich vermute mal das wstring intern viell. n Pointer hat der wild, weils nicht initialisiert ist. Das würd ja verhindert werden, wenn ich nurn Zeiger auf die Klasse hab. Anders könnt ich mir das ehrlich nicht erklären. Klar ist nur das es definitiv daran liegen muss

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gonger96“ ()

    std::wstring ist in sich ein "Smartpointer" (okay, eigentlich nur ein RAII-Container, aber egal). Es sei denn du nutzt new std::wstring (was auch Schwachsinn wäre).
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    Dein Stack ist korrupt (Vermutung). Füge mal ein paar zufällige Datentypen ein, z. B. ein paar int, double und so weiter. Aber wie gesagt - sowas ist schwer zu finden.
    Verwende Valgrind zum Debuggen (oder einen anderen Debugger, der sowas finden kann).
    Oder du ignorierst es und freust dich in Zukunft über weitere, unbehebbare und unerklärliche (Folge)Fehler.
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    Ich muss den Thread leider nochmal ausm Grab hervorhohlen. Heute hatte ich mir vorgenommen das gesamte Eventhandling umzustellen und zwar hab ich für n Event ne map<int, function<...>> um das mehrmals binden zu können. Das hat schön geklappt soweit jetzt wollte ich aber noch 2 Funktionen einbauen einmal Register und UnRegisterCallback. Hat ebenfalls geklappt, da ich aber mehrere EventHandler hab wollt ichs als template Funktion machen aber nun kommt AccessViolation.
    Ich hab also

    C-Quellcode

    1. template <typename EventType>
    2. int RegisterCallback(EventType CallBack, map<int, EventType>& evnt)
    3. {
    4. int sz = evnt.size();
    5. evnt[sz] = bind(CallBack, _1, _2); // Hallo Exception
    6. return sz;
    7. }

    Für EventType wird jetzt function<irgendwas> eingesetzt , CallBack ist der Empfänger und evnt das entsprechende Event der Klasse (map<int, function<...>> Event). Wenn ich anstelle des Templates direkt function<> einsetze, klappts nur wenns mit Template läuft kommt AccessViolation. WEenns mit Template klappen würde wärs klasse, dann bräuchte ich nur eine Registerfunktion für sämtliche EventHandler. Weiß jemand worans liegen könnte ?

    C-Quellcode

    1. int RegisterCallback(EventType CallBack, map<int, function<EventType>>& evnt)


    @Gonger96: Wofür eigentlich eine Map? Dafür nimmst du einen std::vector oder eine std::multimap (bei std::multimap müsste das Konzept aber anders aussehen).
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.