[gelöst] Cast von void* auf BasisKlasse einer "Teilklasse"



  • das Problem ist, ich weis nicht, ob es ein LuaButton oder LuaListView ist

    wenn das gar nicht geht, fällt mir nur noch die Möglichkeit ein, ein struct obendrüber zu setzen

    struct TControlData
    {
      int Typ, //Typ des Controls (LuaButton, LuaListview,...) als const/enum
      void *data;//pointer auf Control
    }
    

    nur wie es mit der speicherreservierung aussieht weis ich dann nicht mehr.
    die Klassen selbst werden mit new erzeugt und per delete freigegeben (sonst werden die beim beenden der Funktion automatisch freigegeben)



  • frank schrieb:

    das Problem ist, ich weis nicht, ob es ein LuaButton oder LuaListView ist

    Dann nimm doch LuaControl* als Zwischenstopp!
    (so, wie ich es in der ersten Antwort schon erwähnt habe)

    #include <iostream>
    
    class LuaControl
    {
    public:
      virtual ~LuaControl() {}
      virtual void foo() = 0;
    };
    
    class LuaButton : public LuaControl
    {
    public:
      void foo() {std::cout<<"LuaButton!\n";}
    };
    
    class LuaListView : public LuaControl
    {
    public:
      void foo() {std::cout<<"LuaListView!\n";}
      void spezifisch() {std::cout<<"LuaListView::spezifisch!\n";}
    };
    
    template<class T> void* voidify(T* ptr)
    {
      LuaControl* zwischenstopp = ptr; // WICHTIG!
      return zwischenstopp;
    }
    
    LuaControl* de_voidify(void* ptr)
    {
      return static_cast<LuaControl*>(ptr);
    }
    
    void who_are_you(void* ptr)
    {
      LuaControl* q = de_voidify(ptr);
      q->foo();
      LuaListView* plv = dynamic_cast<LuaListView*>(q);
      if (plv) {
        plv->spezifisch();
      }
    }
    
    int main()
    {
      LuaButton lb;
      LuaListView llv;
      who_are_you(voidify(&lb));
      who_are_you(voidify(&llv));
    }
    


  • in deinem Code sehe ich aber nicht die Abhängigkeit (Mehrfachvererbung) von LuaButton zu CButton (GtkControl), also nur 1 Basisklasse

    würde es denn gehen, wenn ich in LuaControl hinterlege, dass es sich um ein LuaButton oder LuaListview handelt?

    LuaControl hat mit GtkControl nicht das geringste zu tun, es sind nur 2 Basisklassen.

    Gruß Frank



  • ich habe hier im Forum dieses Topic gefunden, welches mein Problem auch behandelt.
    der Autor kommt zu dem Schluss dass es wohl nicht geht.

    was wäre der beste Ausweg aus der Misere?

    - ein struct obendrüber (pointer und typ siehe oben)
    - eine Ableitung einer Klasse (LuaControl oder C*) mit einem Feld der zweiten Klasse (erstellung im Constructor und freigabe im Destructor), siehe Beispiel

    class LuaButton:public CButton
    {
      public:
        LuaControl *LUA;
    };
    

    letzteres hat natürlich den Nachteil, dass bestimmte Teile (erzeugen und freigeben von LuaControl,, evtl. der [nur lesende] zugriff auf die Variable) immer wieder neu implementiert werden müssten.

    da finde ich die Struct-Variable code-sparender.

    Gruß Frank


  • Administrator

    Du sagst dein Code geht durch Lua? Dann nehme ich mal an, dass du ein Light Userdata verwendest, um den Zeiger durchzureichen. Wieso verwendest du nicht ein normales Userdata? Könntest sizeof(void*) Speicher reservieren lassen, darin den Zeiger speichern und dem Userdata eine eigene Metatable geben. Über die Metatable kannst du die Typen dann unterscheiden. Hier gibt es auch ein paar Beispiele, wie man dies macht: http://www.lua.org/pil/

    Grüssli



  • richtig, ich benutze lightuserdata (pushlightuserdata, lua_touserdata)

    mit metatables kenne ich mich gar nicht aus, kannst du mir ein beispiel geben, wie das aufgebaut ist und wie soetwas angelegt wird?

    mit dem userdata ist ja hier beschrieben...

    ich muss lua-seitig die typen eigentlich nicht unterscheiden, nur auf c++-seite
    prinzipiell denke ich, dass du es so ähnlich aufbauen willst wie meine struct-idee von oben. sehe dem gegenüber jetzt keinen vorteil

    btw. die Vorlage für mein Projekt:
    http://code.google.com/p/scite-ru/source/browse/trunk/lualib/gui/gui_ext.cpp#518

    wie ich gerade sehe, wird da auch newuserdata verwendet, finde nur die stelle nicht, wo die usedata wieder freigegeben wird...

    Gruß Frank


  • Administrator

    frank schrieb:

    , finde nur die stelle nicht, wo die usedata wieder freigegeben wird...

    Muss sie auch nicht, weil ein Userdata vom Lua Garbage Collector verwaltet wird.

    Wenn du mit Lua arbeitest, empfehle ich dir sehr, dass du mal das verlinkte Buch durchliest. Das hat man ziemlich schnell durch und gibt einem einen sehr guten Einstieg in Lua.

    Grüssli



  • momentan sieht es bei mir so aus und ich bekomme einen Segmentation Fault beim zugriff auf ein Feld von WinWrap:

    struct WinWrap {
      int wc;
    	void *window;
    	void *data;
    };
    
    static int wrap_window(lua_State* L, void *win, int WindowClass) 
    {
    	WinWrap *wrp = (WinWrap*)lua_newuserdata(L,sizeof(WinWrap));
    	wrp->window = win;
      wrp->wc=WindowClass;
    	wrp->data = NULL;
    	//luaL_getmetatable(L,WINDOW_CLASS);
    	lua_setmetatable(L,-2);
    	return 1;
    }
    
    //creating a class and pushing winwrap-pointer to lua stack:
      LuaListView *Listview=new LuaListView(L,GTK_WIDGET(iParent));
      /* //old code
        lua_pushlightuserdata(L,Listview);//put pointer of Listview to stack
        return 1;//return 1 value (handle)
      */
      return wrap_window(L,Listview, lcListView);
    
    //now accessing the winwrap
    static int do_ListViewAddColumn(lua_State *L) //gui.Listview_Add_Column(Listview,"caption")
    {
      void *iLuaControl=lua_touserdata(L,1);
      const char *caption=luaL_checkstring(L,2);
    
      g_print("Listview->AddColumn\n");
    
      WinWrap *wrp=(WinWrap*)iLuaControl;
      //LuaListView *Listview=reinterpret_cast<LuaListView*>(iLuaControl);
      if (wrp->wc==lcListView) //<= Segmentation Fault
      {
        g_print("Listview:CastToLuaListview\n");
        LuaListView *Listview=reinterpret_cast<LuaListView*>(wrp->window);
        Listview->AddColumn(caption);
      }
      //lua_pushlightuserdata(L,vbox);//put pointer of vbox on stack
      return 0;//return 1 value (handle)
    }
    

    hat jemand eine Idee?


  • Administrator

    Mit diesen wenigen Informationen schwer zu sagen. Vor allem auch wegen Lua, da man schnell darüber Fehler erzeugt, bzw. mit der API die falschen Daten lädt oder speichert. Zum Beispiel kommt mir dein Code sehr verdächtig vor an der Zeile 14. Nach lua_newuserdata lädst du nirgends die Metatable, dabei muss die Metatable an der Position -1 zu finden sein.

    Am besten prüfst du mal, welcher Zeigerwert du am Anfang hast und welcher du hast, wenn du ihn ausliest.

    Grüssli



  • Danke, die metatable war das problem...hab sie erstmal raus (war aus meiner Vorlage) und schon funktionert es.

    Danke


Anmelden zum Antworten