libsigc++ eigenes Signal unter GTKmm



  • Moin

    ich möchte in einigen meiner Klassen eigene Signale einbetten, ich habe mir das überlegt, aber es kam beim connect(...) zu einem Fehler. Dann habe ich mich umgeschaut und folgendes gefunden http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/apc.html exakt so habe ich es gemacht, aber es will nicht. Schaut euch meinen Code an, ich brauche es für die Uni, ist also nicht unwichtig.
    Header

    #include <gtkmm.h>
    
    class AVTab : public Gtk::Table
    {
    	typedef sigc::signal<void, AVTab*> type_sigCloseTab;	
    
    private:
    	/*...*/
    
    protected:
    	type_sigCloseTab m_sigCloseTab;
    public:
    	AVTab();
    	~AVTab();
    
    	type_sigCloseTab signal_closetab() {return m_sigCloseTab;};
    };
    

    Code

    #include "AVTab.h"
    
    AVTab::AVTab()
    :	Gtk::Table(2,2),
    /*...*/
    {
    /*...*/
    	show_all();
    }
    AVTab::~AVTab()
    {
    
    }
    

    Client

    AVTab* tab = Gtk::manage(new AVTab());
    
    	m_Tabs.append_page(*tab, tab->get_PageLabel());
    	tab->signal_closetab()->connect(sigc::mem_fun(*this, &AVMainWindow::onCloseTab));
    

    Der Zugriffsfehler wird dann wärend des connects in einer xutility Datei verursacht, bei dem ersten while (Zeile 174).

    void __CLR_OR_THIS_CALL _Orphan_me()
    		{	// cut ties with parent
    		if (_Mycont != 0 && _Mycont->_Myfirstiter != _IGNORE_MYITERLIST)
    			{	// adopted, remove self from list
    			_Iterator_base **_Pnext =
    				(_Iterator_base **)&_Mycont->_Myfirstiter;
    			while (*_Pnext != 0 && *_Pnext != this)
    				_Pnext = &(*_Pnext)->_Mynextiter;
    
    			if (*_Pnext == 0)
    				_DEBUG_ERROR("ITERATOR LIST CORRUPTED!");
    			*_Pnext = _Mynextiter;
    			_Mycont = 0;
    			}
    		}
    

    MfG Protogenes

    P.S. Ich nutze VS2005 Professional und GTKmm 2.10.8-1



  • tab->signal_closetab()->connect(sigc::mem_fun(*this, &AVMainWindow::onCloseTab)); ➡
    tab->signal_closetab().connect(sigc::mem_fun(*this, &AVMainWindow::onCloseTab));



  • GPC schrieb:

    tab->signal_closetab()->connect(sigc::mem_fun(*this, &AVMainWindow::onCloseTab)); ➡
    tab->signal_closetab().connect(sigc::mem_fun(*this, &AVMainWindow::onCloseTab));

    ja ok das ist klar, ich hatte ein wenig umherprobiert und das Signalobjekt als Pointer definiert und mit new erzeugt. Da ist mir wohl ein kleiner Fehler unterlaufen, als ich es hier gepostet habe. Also nein, das ist nicht der Fehler, kompiliert wird ja, der Fehler tritt zur Laufzeit auf.
    Hier mal noch der Callstack:

    >	AudioVisD.exe!std::_Iterator_base::_Orphan_me()  Zeile 174 + 0x3 Bytes	C++
     	AudioVisD.exe!std::_Iterator_base::~_Iterator_base()  Zeile 151	C++
     	AudioVisD.exe!std::_Bidit<sigc::slot_base,int,sigc::slot_base const *,sigc::slot_base const &>::~_Bidit<sigc::slot_base,int,sigc::slot_base const *,sigc::slot_base const &>()  + 0x16 Bytes	C++
     	AudioVisD.exe!std::list<sigc::slot_base,std::allocator<sigc::slot_base> >::_Const_iterator<1>::~_Const_iterator<1>()  + 0x16 Bytes	C++
     	AudioVisD.exe!std::list<sigc::slot_base,std::allocator<sigc::slot_base> >::_Iterator<1>::~_Iterator<1>()  + 0x16 Bytes	C++
     	AudioVisD.exe!sigc::signal1<void,AVTab &,sigc::nil>::connect(const sigc::slot<void,AVTab &,sigc::nil,sigc::nil,sigc::nil,sigc::nil,sigc::nil,sigc::nil> & slot_={...})  Zeile 1799 + 0x95 Bytes	C++
     	AudioVisD.exe!AVMainWindow::addFile(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & filename="asf")  Zeile 115 + 0x74 Bytes	C++
    

    MfG Protogenes



  • Hallo,

    folgender Code kompiliert bei mir und läuft auch sauber:

    #include <gtkmm.h>
    
    class AVTab : public Gtk::Table
    {
        typedef sigc::signal<void, AVTab*> type_sigCloseTab;   
    
    private:
        /*...*/
    
    protected:
        type_sigCloseTab m_sigCloseTab;
    public:
        AVTab();
        ~AVTab();
    
        type_sigCloseTab signal_closetab() {return m_sigCloseTab;};
    };
    
    AVTab::AVTab() : Gtk::Table(2,2)
    {
    
        show_all_children();
    }
    
    AVTab::~AVTab()
    {
    
    }
    
    class Client : public Gtk::Window {
    public:
      Client () {
        AVTab* tab = Gtk::manage(new AVTab());
    
        //m_Tabs.append_page(*tab, tab->get_PageLabel());
        tab->signal_closetab().connect(sigc::mem_fun(*this, &Client::foo));
    
      }
    
      void foo(AVTab *) {
    
      }
    
    };
    
    int main(int argc, char **argv) {
      Gtk::Main m(&argc, &argv);
      Client c;
    
      m.run(c);
    
      return 0;
    }
    

    Ähm, sonst stell mir mal ein minimales, aber ohne weiteres kompilierbare, Beispiel zur Verfügung, dass bei dir kompiliert und dann crasht.

    MfG

    GPC



  • Hallo GPC, danke für dein Interesse.
    Also dein Beispiel ist ja als minimal zu bezeichnen und es kompiliert bei mir. Aber es läuft nicht. Selbe Stelle wie oben, irgendwie im std::list iterator.
    Bei dir im VS2005Pro ?
    MfG Protogenes



  • Ich habe jetzt mal noch VS2003Pro installiert und dein Beispiel damit versucht zu erstellen. Da streikt der Linker

    test error LNK2019: Nicht aufgelöstes externes Symbol '"__declspec(dllimport) protected: class std::list<class sigc::slot_base,class std::allocator<class sigc::slot_base> >::iterator __thiscall sigc::signal_base::connect(class sigc::slot_base const &)" (__imp_?connect@signal_base@sigc@@IAE?AViterator@?$list@Vslot_base@sigc@@V?$allocator@Vslot_base@sigc@@@std@@@std@@ABVslot_base@2@@Z)', verwiesen in Funktion '"public: struct sigc::slot_iterator<class sigc::slot<void,class AVTab *,struct sigc::nil,struct sigc::nil,struct sigc::nil,struct sigc::nil,struct sigc::nil,struct sigc::nil> > __thiscall sigc::signal1<void,class AVTab *,struct sigc::nil>::connect(class sigc::slot<void,class AVTab *,struct sigc::nil,struct sigc::nil,struct sigc::nil,struct sigc::nil,struct sigc::nil,struct sigc::nil> const &)" (?connect@?$signal1@XPAVAVTab@@Unil@sigc@@@sigc@@QAE?AU?$slot_iterator@V?$slot@XPAVAVTab@@Unil@sigc@@U23@U23@U23@U23@U23@@sigc@@@2@ABV?$slot@XPAVAVTab@@Unil@sigc@@U23@U23@U23@U23@U23@@2@@Z)'
    

    Ich habe die Einstellungen (wie Abhängigkeiten und Suchpfade) etliche male überprüft, überprüfen lassen und mit dem 2005er Projekt verglichen.

    Eine reine simple GTK Anwendung erstellt er zwar, stürzt aber bei jedem show_all() oder show_all_children() ab.
    Das einfach noch als Informationen, vielleicht hilft es ja.
    Wenn mir jemand erklärt, wie ich und in welcher Reihenfolge die GTKmm Pakete kompiliere, dann würde ich es mal mit der neueren 2.10.10 statt der 2.0.8 probieren.

    MfG Protogenes

    P.S. sorry für das doppelposting



  • Protogenes schrieb:

    Hallo GPC, danke für dein Interesse.
    Also dein Beispiel ist ja als minimal zu bezeichnen und es kompiliert bei mir. Aber es läuft nicht. Selbe Stelle wie oben, irgendwie im std::list iterator.

    Schaut nach 'nem Bug in deinem gtkmm Build aus.

    Bei dir im VS2005Pro ?

    Ne, der aktuelle GCC unter Linux und das aktuelle gtkmm.

    Protogenes schrieb:

    Wenn mir jemand erklärt, wie ich und in welcher Reihenfolge die GTKmm Pakete kompiliere, dann würde ich es mal mit der neueren 2.10.10 statt der 2.0.8 probieren.

    Mit dem VC05 habe ich das noch nie gemacht. Früher habe ich mir mein gtkmm immer mit dem MinGW und der msys Shell zusammenkompiliert. Aber wieso kompilieren, wenn's die 2.10er auch hier zum Download gibt?

    Probier's einfach mal damit und gib dann Bescheid, ob sich was geändert hat.



  • GPC schrieb:

    Schaut nach 'nem Bug in deinem gtkmm Build aus.
    Ne, der aktuelle GCC unter Linux und das aktuelle gtkmm.

    Ich habe das Gefühl es liegt am Zusammenspiel von MS VS2005 und Gtkmm. Der Fehler tritt ja erst in einer std::list auf. Aber eigentlich sollte die StandardLib schn korrekt sein. Es ist aber meist so, dass der Fehler irgendwo auftritt, wenn man selbst einen Fehler macht.

    GPC schrieb:

    Probier's einfach mal damit und gib dann Bescheid, ob sich was geändert hat.

    Ja meinen Build habe ich von dort, die 2.10.8. Es gibt ja aber schon eine neuere Revision 2.10.10 (ich habe mich vertippt im vorhergehenden Post, da meine 1 klemmt, sorry)

    MfG Protogenes



  • Möglichkeit A: IDE bzw. Compiler wechseln (Code::Blocks mit MinGW).
    Möglichkeit B: gtkmm selber kompilieren (zuerst libsigc++, dann glibmm und dann gtkmm).



  • Code::Blocks war ein guter Tipp, damit geht es. Ist zwar beiweitem nicht so komfortabel, aber was solls, wird mein Softwarepraktikum schon überstehen.
    Danke GPC



  • Hast du dir den Release Candidate gezogen? Der ist nämlich schon steinalt. Die aktuellen Nightly Builds (die geistern auch auf der Homepage rum) sind tagesaktuell und auch weitaus komfortabler. Brauchst dir auch keine Sorgen wegen Beta-Stadium o.ä. zu machen, die sind stabil.



  • Also ich hab das bei mir nicht probieren können, weil gestern ein Stromausfall war und mein Windows nicht mehr bootbar ist...

    Eine Vermutung:
    Der Fehler tritt bei der Zerstörung eines temporären Iterators auf; der Iterator geht auf eine Liste des Signals, das in der sigc++.dll lebt. Der Iterator selbst lebt aber in der exe.
    Mich wundert zwar, dass die Dereferenzierung des Iterators schon Probleme bereitet, aber die Frage ist, ob der Iterator über dll-Grenzen hinweg gültig ist.

    Ich weiss z.B., dass du nicht ohne Weiteres Speicher in einer DLL reservieren kannst und in einer exe wieder freigeben.

    Das hängt davon ab, ob deine dll und deine exe beide mit einer dll-runtime gelinkt worden sind oder mit einer statischen runtime.

    Jedenfalls ist das mit der dll auch der Grund, warum MSVC 2003 den Iterator nicht als Linkersymbol findet, weil die dll den Iteratortyp nicht exportiert.

    Probier mal, die sigc++.dll selber zu kompilieren und sie und deine exe mit der dll-runtime zu linken und schau dann, was passiert.



  • Moin

    @triendl.kj
    also ich habe libsigc++ selber kompiliert mit den enthaltenen VS Projektdateien. Habe die includes und linker Verweise agepasst, die "alten" Dlls ersetzt etc.
    Es ging aber immer noch nicht. Also entweder ich habe iwo was vergessen zu ersetzen (kann durchaus möglich sein) oder es liegt woanders.
    Ich stelle mich (solange es meine Zeit erlaubt) noch weiterhin als Testperson zur Verfügung ^^

    @GPC Ich habe mir die Nigthly gezogen, die ist gleich wesentlich besser, ist ja auch 17 Monate neuer XD Habe ich gar nicht gesehen gehabt, als ich mir die Stable zog, ich bin da sonst auch nicht so vorsichtig ^^
    Ich werde dieses Projekt mit C::B weitermachen, da das Projekt auch plattformübergreifend sein soll und sich da C::B anbietet. Nochmal danke für den Tip.

    MfG Protogenes



  • Also, ich hab das kleine Beispielprogramm bei mir ausprobiert und es funktioniert einwandfrei.
    Hab allerdings gtkmm/sigc++ nicht selber kompiliert, sondern den gtkmm-2.10-Installer und gtk+-Installer für Windows-Binaries über http://www.pcpm.ucl.ac.be/~gustin/win32_ports/ bezogen.



  • triendl.kj schrieb:

    Also, ich hab das kleine Beispielprogramm bei mir ausprobiert und es funktioniert einwandfrei.
    Hab allerdings gtkmm/sigc++ nicht selber kompiliert, sondern den gtkmm-2.10-Installer und gtk+-Installer für Windows-Binaries über http://www.pcpm.ucl.ac.be/~gustin/win32_ports/ bezogen.

    Daher habe ich ja auch meine Headers und Binaries. Aber bei mir geht es nicht. Ich hab keine Erklärung für das unterschiedliche Verhalten.



  • tja, falls es dich noch interessiert oder wichtig für dich ist, könnte ich dir noch anbieten, mir dein Projekt des Beispielprogramms zu schicken. Vielleicht entdecke ich was...


Anmelden zum Antworten