Lua-Objekte



  • Hallo,
    ich habe mein Projekt soweit, dass ich verschiedene Objekte anlegen kann und über Funktionen diese bearbeiten kann.

    bisher sieht das lua-seitig so aus:

    local lv=gui.New_Listview(pc1tab1)
    gui.Listview_Add_Column(lv,"Col 1")
    

    nun möchte ich das ganze so umbauen:

    local lv=ListView.new(pc1tab1)
    lv:Add_Column("Col 1")
    

    dazu habe ich versucht mich hieran zu halten:

    static const struct luaL_reg ListView_f [] = {
      {"new", do_CreateListView},
      {NULL, NULL}
    };
    
    static const struct luaL_reg ListView_m [] = {
      { "Add_Column", do_ListViewAddColumn },
      { "Add_Item", do_ListViewAddItem },
      { "Set_Item", do_ListViewSetItem },
      { "Get_Text", do_ListViewGetText },
      { "Clear", do_ListViewClear },
      {NULL, NULL}
    };
    
    extern "C" 
    {
      LUALIB_API int luaopen_gui(lua_State *L)
      {
        luaL_newmetatable(L, "gui.ListView");
    
        lua_pushstring(L, "__index");
        lua_pushvalue(L, -2);  /* pushes the metatable */
        lua_settable(L, -3);  /* metatable.__index = metatable */
    
        luaL_openlib(L, NULL, ListView_m, 0); //first register Methods
        luaL_openlib(L, "ListView", ListView_f, 0); //now register object 
        return 1;
      }
    }
    

    das Listview wird korrekt erzeugt, jedoch bekomme ich beim Zugriff auf das Objekt lv den folgenden Fehler:

    attempt to index local 'lv' (a userdata value)
    

    Es ist mir auch klar, dass es ein userdata ist, da ich das Objekt wie folgt erstellt habe:

    static int do_CreateListView(lua_State *L)
    {
      void *iParent=lua_touserdata(L,1);
      LuaListView *Listview=new LuaListView(L,GTK_WIDGET(iParent));
      lua_pushlightuserdata(L,Listview);//put pointer of Listview to stack
      return 1;//return 1 value (handle)
    }
    

    geht das mit userdata nicht? bzw. wie müsste es aussehen? da habe ich in der doku keinen Hinweis gefunden

    Gruß Frank


  • Administrator

    Wenn du das Buch vollständig lesen würdest, hättest du alle Informationen, welche du benötigst.
    1. Ein Light-Userdata kann keine Metatable haben und somit nicht als Objekt verwendet werden.
    2. Jedem Userdata muss man die gleiche Metatable zuweisen, welche die Klasse beschreibt. Du weist die Metatable aber nirgends dem Objekt zu.

    Ich kann dir nur empfehlen, zuerst das ganze Buch zu lesen. Dann erfährst du auch, wieso man die Objektorientierung über die Metatable machen kann. Wenn man die vorherigen Kapitel gelesen hat, ist das von dir verlinkte Kapitel nur noch eine Art Ideengeber. Ich hatte zu dem Zeitpunkt bereits eigene Ideen für die Objektorientierung in Lua entwickelt. Man hat das Buch innert ein paar Stunden durch, nimm dir die Zeit.

    Grüssli



  • Danke für den Hinweis,
    ich brauche also eine normale Userdata (ohne Light), das zuweisen ist mir auch klar, nur wie bekomme ich da meinen Klassenpointer rein?
    Userdata erzeugt ja einen eigenen Speicherbereich bestimmter Größe, aber hat kein feld um einen Pointer auf die erzeugte klasse zu hinterlegen.

    muss ich da den weg über ein übergeordnetes struct gehen?

    so in etwa:

    struct LuaClass
    {
      void *ClassPointer;
      int ClassType;
    }
    
    LuaClass *lc = (LuaClass*)lua_newuserdata(L,sizeof(LuaClass));
    lc->ClassPointer = Listview;
    lc->ClassType = cListView;
    luaL_getmetatable(L,"gui.ListView");
    lua_setmetatable(L,-2);
    return 1;
    

    ich glaube für das ganze Buch brauche ich Wochen 😉 in deutsch gibts das nicht, oder?
    nachschlagen in englisch ist ja ok für mich, aber eine komplette Dokumentation ist schon heftig. zumal ich die von Lua ziemlich verwirrend finde
    ich lese mir aber zumindest mal das aktuelle Kapitel durch

    Gruß Frank


  • Administrator

    frank schrieb:

    ich glaube für das ganze Buch brauche ich Wochen 😉 in deutsch gibts das nicht, oder?

    Doch, aber soweit ich weiss nicht kostenlos. Die kostenlose Version ist ja auch nicht die aktuellste. Die aktuelle Version ist:
    Programming in Lua | ISBN: 9788590379829

    Davon gibt es eine Übersetzung:
    Programmieren mit Lua | ISBN: 3937514228

    Du solltest dich aber unbedingt an englische Dokumentationen und Bücher gewöhnen. In der Informatik kommt man nicht sehr weit ohne gute Englischkenntnisse.

    frank schrieb:

    Danke für den Hinweis,
    ich brauche also eine normale Userdata (ohne Light), das zuweisen ist mir auch klar, nur wie bekomme ich da meinen Klassenpointer rein?
    Userdata erzeugt ja einen eigenen Speicherbereich bestimmter Größe, aber hat kein feld um einen Pointer auf die erzeugte klasse zu hinterlegen.

    muss ich da den weg über ein übergeordnetes struct gehen?

    Die Wege sind zahlreich. Du kannst ja ALLES darin abspeichern. Du kannst auch nur Speicher für einen Zeiger holen und speicherst dann diesen Zeiger darin. Den Klassentyp brauchst du nämlich eigentlich nicht zu speichern. Über die Metatable kannst du bereits herausfinden, von welchem Typ das Userdata ist. Aus dem Lua Code darf die Metatable eines Userdata nicht verändert werden. Siehe auch:
    http://www.lua.org/manual/5.1/manual.html#2.2
    http://www.lua.org/manual/5.1/manual.html#luaL_checkudata

    luaL_checkudata kannst du natürlich nur verwenden, wenn du vorher die Metatable mit luaL_newmetatable angelegt hast und der auxiliary Bibliothek somit bekannt ist.

    Grüssli


Anmelden zum Antworten