Browse Source

It works! Kind of. Well, no crashes.

Added a check to see if a LuaType is reference counted.

I probably forgot to remove a whole bunch of debugging code, so if you see poorly placed strings everywhere, that was me trying to figure out what was going on.
Nate Starkey 13 years ago
parent
commit
23ef189318

+ 5 - 1
Include/Rocket/Core/Lua/LuaType.h

@@ -39,7 +39,7 @@ namespace Lua {
     template<> luaL_reg* GetAttrTable<type>() { return type##Getters; } \
     template<> luaL_reg* SetAttrTable<type>() { return type##Setters; } \
 
-//put this in the type.h file  NOT USED at this moment
+//put this in the type.h file
 #define LUATYPEDECLARE(type) \
     template<> const char* GetTClassName<type>(); \
     template<> RegType<type>* GetMethodTable<type>(); \
@@ -97,6 +97,10 @@ public:
     static  void extra_init(lua_State* L, int metatable_index);
     //Registers methods,getters,and setters to the type
     static void _regfunctions(lua_State* L, int meta, int method);
+    //Says if it is a reference counted type. If so, then on push and __gc, do reference counting things
+    //rather than regular new/delete. Note that it is still up to the user to pass "true" to the push function's
+    //third parameter to be able to decrease the reference when Lua garbage collects an object
+    static bool is_reference_counted();
 private:
     LuaType(); //hide constructor
 

+ 1 - 1
Samples/luainvaders/data/main_menu.rml

@@ -32,6 +32,6 @@ end
 		<button onclick="Window.LoadMenu('high_score')">High Scores</button><br />
 		<button onclick="Window.LoadMenu('options')">Options</button><br />
 		<button onclick="Window.LoadMenu('help')">Help</button><br />
-		<button onclick="game.Shutdown()">Exit</button>
+		<button onclick="Game.Shutdown()">Exit</button>
 	</body>
 </rml>

+ 0 - 4
Samples/luainvaders/lua/start.lua

@@ -1,11 +1,7 @@
 
 function Startup()
-    --for k,v in pairs(rocket) do Log(k) end
-    --yes, maincontext is supposed to be global
-    --rocket.CreateContext("notmain",Vector2i(20,15))
     local escape = rocket.key_identifier["ESCAPE"]
     if escape ~= nil then
-    
         maincontext = rocket.contexts()["main"]
         maincontext:LoadDocument("data/background.rml"):Show()
         local doc = maincontext:LoadDocument("data/main_menu.rml")

+ 7 - 7
Samples/luainvaders/src/LuaInterface.cpp

@@ -57,16 +57,16 @@ void LuaInterface::InitGame(lua_State *L)
     lua_pushcfunction(L,GameSetHighScoreName);
     lua_setfield(L,game,"SetHighScoreName");
 
-    lua_newtable(L);
-    lua_pushinteger(L,GameDetails::HARD);
-    lua_setfield(L,-2,"HARD");
+    lua_newtable(L); //table, Game
+    lua_pushinteger(L,GameDetails::HARD); //int,table,Game
+    lua_setfield(L,-2,"HARD");//table,Game
 
-    lua_pushinteger(L,GameDetails::EASY);
-    lua_setfield(L,-2,"EASY");
+    lua_pushinteger(L,GameDetails::EASY); //int,table,Game
+    lua_setfield(L,-2,"EASY"); //table,Game
 
-    lua_setfield(L,game,"difficulty"); //Game.difficulty = {HARD,EASY}
+    lua_setfield(L,game,"difficulty"); //Game
 
-    lua_pop(L,2); //pop both Game.difficulty and Game
+    lua_pop(L,1); //pop Game
 }
 
 int GameShutdown(lua_State* L)

+ 2 - 1
Samples/luainvaders/src/main.cpp

@@ -37,6 +37,7 @@
 #include "ElementGame.h"
 #include "HighScores.h"
 #include <Rocket/Core/Lua/Interpreter.h>
+#include "LuaInterface.h"
 
 Rocket::Core::Context* context = NULL;
 
@@ -122,7 +123,7 @@ int main(int, char**)
 
 	// Fire off the startup script.
 	//PythonInterface::Import("autoexec");
-    //LuaInterface::Initialise(Interpreter::GetLuaState());
+    LuaInterface::Initialise(Rocket::Core::Lua::Interpreter::GetLuaState());
     Rocket::Core::Lua::Interpreter::LoadFile(Rocket::Core::String(APP_PATH).Append("lua/start.lua"));
 
 	Shell::EventLoop(GameLoop);	

+ 1 - 0
Source/Controls/Lua/ElementDataGrid.h

@@ -23,6 +23,7 @@ namespace Core {
 namespace Lua {
 //this will be used to "inherit" from Element
 template<> void LuaType<ElementDataGrid>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementDataGrid>::is_reference_counted();
 
 //methods
 int ElementDataGridAddColumn(lua_State* L, ElementDataGrid* obj);

+ 1 - 0
Source/Controls/Lua/ElementDataGridRow.h

@@ -27,6 +27,7 @@ namespace Core {
 namespace Lua {
 //this will be used to "inherit" from Element
 template<> void LuaType<ElementDataGridRow>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementDataGridRow>::is_reference_counted();
 
 //getters
 int ElementDataGridRowGetAttrrow_expanded(lua_State* L);

+ 1 - 0
Source/Controls/Lua/ElementForm.h

@@ -18,6 +18,7 @@ namespace Core {
 namespace Lua {
 //this will be used to "inherit" from Element
 template<> void LuaType<ElementForm>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementForm>::is_reference_counted();
 
 //method
 int ElementFormSubmit(lua_State* L, ElementForm* obj);

+ 2 - 0
Source/Controls/Lua/ElementFormControl.h

@@ -17,6 +17,8 @@ namespace Rocket {
 namespace Core {
 namespace Lua {
 template<> void LuaType<ElementFormControl>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementFormControl>::is_reference_counted();
+
 //getters
 int ElementFormControlGetAttrdisabled(lua_State* L);
 int ElementFormControlGetAttrname(lua_State* L);

+ 1 - 0
Source/Controls/Lua/ElementFormControlDataSelect.h

@@ -20,6 +20,7 @@ namespace Core {
 namespace Lua {
 //inherits from ElementFormControl which inherits from Element
 template<> void LuaType<ElementFormControlDataSelect>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementFormControlDataSelect>::is_reference_counted();
 
 //method
 int ElementFormControlDataSelectSetDataSource(lua_State* L, ElementFormControlDataSelect* obj);

+ 1 - 0
Source/Controls/Lua/ElementFormControlInput.h

@@ -23,6 +23,7 @@ namespace Core {
 namespace Lua {
 //inherits from ElementFormControl which inherits from Element
 template<> void LuaType<ElementFormControlInput>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementFormControlInput>::is_reference_counted();
 
 //getters
 int ElementFormControlInputGetAttrchecked(lua_State* L);

+ 1 - 0
Source/Controls/Lua/ElementFormControlSelect.h

@@ -29,6 +29,7 @@ namespace Core {
 namespace Lua {
 //inherits from ElementFormControl which inherits from Element
 template<> void LuaType<ElementFormControlSelect>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementFormControlSelect>::is_reference_counted();
 
 //methods
 int ElementFormControlSelectAdd(lua_State* L, ElementFormControlSelect* obj);

+ 1 - 0
Source/Controls/Lua/ElementFormControlTextArea.h

@@ -20,6 +20,7 @@ namespace Core {
 namespace Lua {
 //inherits from ElementFormControl which inherits from Element
 template<> void LuaType<ElementFormControlTextArea>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementFormControlTextArea>::is_reference_counted();
 
 //getters
 int ElementFormControlTextAreaGetAttrcols(lua_State* L);

+ 1 - 0
Source/Controls/Lua/ElementTabSet.h

@@ -26,6 +26,7 @@ namespace Core {
 namespace Lua {
 //this will be used to "inherit" from Element
 template<> void LuaType<ElementTabSet>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<ElementTabSet>::is_reference_counted();
 
 //methods
 int ElementTabSetSetPanel(lua_State* L, ElementTabSet* obj);

+ 1 - 1
Source/Controls/Lua/LuaDataSource.h

@@ -9,7 +9,7 @@ namespace Rocket {
 namespace Core {
 namespace Lua {
 
-class LuaDataSource : public DataSource
+class LuaDataSource : public Rocket::Controls::DataSource
 {
 public:
     //default initilialize the lua func references to -1

+ 1 - 0
Source/Core/Lua/Context.h

@@ -36,6 +36,7 @@
 namespace Rocket {
 namespace Core {
 namespace Lua {
+template<> bool LuaType<Context>::is_reference_counted();
 
 //methods
 int ContextAddEventListener(lua_State* L, Context* obj);

+ 1 - 0
Source/Core/Lua/Document.h

@@ -33,6 +33,7 @@ namespace Lua {
 typedef ElementDocument Document;
 
 template<> void LuaType<Document>::extra_init(lua_State* L, int metatable_index);
+template<> bool LuaType<Document>::is_reference_counted();
 
 //methods
 int DocumentPullToFront(lua_State* L, Document* obj);

+ 1 - 1
Source/Core/Lua/Element.h

@@ -89,7 +89,7 @@
 namespace Rocket {
 namespace Core {
 namespace Lua {
-
+template<> bool LuaType<Element>::is_reference_counted();
 
 //methods
 int ElementAddEventListener(lua_State* L, Element* obj);

+ 1 - 0
Source/Core/Lua/Event.h

@@ -20,6 +20,7 @@
 namespace Rocket {
 namespace Core {
 namespace Lua {
+template<> bool LuaType<Event>::is_reference_counted();
 
 //method
 int EventStopPropagation(lua_State* L, Event* obj);

+ 5 - 1
Source/Core/Lua/Interpreter.cpp

@@ -91,7 +91,7 @@ void Interpreter::Report()
     const char * msg= lua_tostring(_L,-1);
     while(msg)
     {
-        lua_pop(_L,-1);
+        lua_pop(_L,1);
         Log::Message(Log::LT_WARNING, msg);
         msg=lua_tostring(_L,-1);
     }
@@ -107,6 +107,10 @@ bool Interpreter::ExecuteCall(int params, int res)
 {
     bool ret = true;
     int top = lua_gettop(_L);
+    //String strtype = lua_typename(_L,top-params);
+    String strtype;
+    for(int i = top; i >= 1; i--)
+        strtype = lua_typename(_L,lua_type(_L,i));
     if(lua_type(_L,top-params) != LUA_TFUNCTION)
     {
         ret = false;

+ 25 - 5
Source/Core/Lua/LuaEventListener.cpp

@@ -15,11 +15,26 @@ LuaEventListener::LuaEventListener(const String& code, Element* element) : Event
     function.Append(" end");
 
     lua_State* L = Interpreter::GetLuaState();
+    lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
+    if(lua_isnoneornil(L,-1))
+    {
+        lua_newtable(L);
+        lua_setglobal(L,"EVENTLISTENERFUNCTIONS");
+        lua_pop(L,1); //pop the unsucessful getglobal
+        lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
+    }
+    int tbl = lua_gettop(L);
+    strFunc = lua_typename(L,lua_type(L,tbl));
 
     luaL_loadstring(L,function.CString()); //pushes the compiled string to the top of the stack
-    luaFuncRef = lua_ref(L,true); //creates a reference to the item at the top of the stack
+    if(lua_pcall(L,0,1,0) != 0)
+        Interpreter::Report();
+    strFunc = lua_typename(L,lua_type(L,-1));
+    luaFuncRef = luaL_ref(L,tbl); //creates a reference to the item at the top of the stack in to the table we just created
+    lua_pop(L,1); //pop the EVENTLISTENERFUNCTIONS table
     attached = element;
     parent = element->GetOwnerDocument();
+    strFunc = function;
 }
 
 //if it is created from a Lua Element
@@ -34,13 +49,18 @@ LuaEventListener::LuaEventListener(int ref, Element* element)
 void LuaEventListener::ProcessEvent(Event& event)
 {
     lua_State* L = Interpreter::GetLuaState();
+    String strtype;
     int top = lua_gettop(L); 
     //push the arguments
-    LuaType<Event>::push(L,&event,false);
-    LuaType<Element>::push(L,attached,false);
-    LuaType<Document>::push(L,parent,false);
+    lua_getglobal(L,"EVENTLISTENERFUNCTIONS");
+    int table = lua_gettop(L); //needed for lua_remove
+    strtype = lua_typename(L,lua_type(L,table));
+    lua_rawgeti(L,table,luaFuncRef);
+    strtype = lua_typename(L,lua_type(L,-1));
+    strtype = lua_typename(L,lua_type(L,LuaType<Event>::push(L,&event,false)));
+    strtype = lua_typename(L,lua_type(L,LuaType<Element>::push(L,attached,false)));
+    strtype = lua_typename(L,lua_type(L,LuaType<Document>::push(L,parent,false)));
     
-    lua_getref(L,luaFuncRef);
     Interpreter::ExecuteCall(3,0); //call the function at the top of the stack with 3 arguments
 
     lua_settop(L,top); //balanced stack makes Lua happy

+ 2 - 0
Source/Core/Lua/LuaEventListener.h

@@ -1,5 +1,6 @@
 #pragma once
 #include <Rocket/Core/EventListener.h>
+#include <Rocket/Core/String.h>
 #include "lua.hpp"
 
 namespace Rocket {
@@ -25,6 +26,7 @@ private:
     int luaFuncRef;
     Element* attached;
     ElementDocument* parent;
+    String strFunc; //for debugging purposes
 };
 
 }

+ 25 - 2
Source/Core/Lua/LuaType.cpp

@@ -79,11 +79,21 @@ int LuaType<T>::push(lua_State *L, T* obj, bool gc)
             lua_pushboolean(L,1);// ->[4] = true
             lua_setfield(L,-2,name); //represents t[k] = v, [-2 = 3] = t -> v = [4], k = <ClassName>; pop [4]
         }
+        else
+        {
+            if(is_reference_counted())
+                ((Rocket::Core::ReferenceCountable*)obj)->AddReference();
+        }
         lua_pop(L,1); // -> pop [3]
     }
+    String strtype = lua_typename(L,ud);
+    strtype = lua_typename(L,mt);
     lua_settop(L,ud); //[ud = 2] -> remove everything that is above 2, top = [2]
+    strtype = lua_typename(L,-1);
     lua_replace(L, mt); //[mt = 1] -> move [2] to pos [1], and pop previous [1]
+    strtype = lua_typename(L,-1);
     lua_settop(L, mt); //remove everything above [1]
+    strtype = lua_typename(L,-1);
     return mt;  // index of userdata containing pointer to T object
 }
 
@@ -134,8 +144,15 @@ int LuaType<T>::gc_T(lua_State* L)
         lua_getfield(L,-1, std::string(name).c_str()); //[-1 = 2] -> [3] = the value returned from if <ClassName> exists in the table to not gc
         if(lua_isnil(L,-1) ) //[-1 = 3] if it doesn't exist, then we are free to garbage collect c++ side
         {
-            delete obj;
-            obj = NULL;
+            if(is_reference_counted())
+            {
+                ((Rocket::Core::ReferenceCountable*)obj)->RemoveReference();
+            }
+            else
+            {
+                delete obj;
+                obj = NULL;
+            }
         }
     }
     lua_pop(L,3); //balance function
@@ -277,6 +294,12 @@ void LuaType<T>::_regfunctions(lua_State* L, int meta, int methods)
     lua_setfield(L,methods, "__setters"); //[methods = 1], methods.__setters = table, pop table
 }
 
+template<typename T>
+bool LuaType<T>::is_reference_counted()
+{
+    return false;
+}
+
 }
 }
 }

+ 4 - 0
Source/Core/Lua/LuaType.h

@@ -97,6 +97,10 @@ public:
     static  void extra_init(lua_State* L, int metatable_index);
     //Registers methods,getters,and setters to the type
     static void _regfunctions(lua_State* L, int meta, int method);
+    //Says if it is a reference counted type. If so, then on push and __gc, do reference counting things
+    //rather than regular new/delete. Note that it is still up to the user to pass "true" to the push function's
+    //third parameter to be able to decrease the reference when Lua garbage collects an object
+    static bool is_reference_counted();
 private:
     LuaType(); //hide constructor
 

+ 16 - 2
Source/Core/Lua/LuaTypeTemplateSpec.inl

@@ -81,6 +81,22 @@ template class LuaType<ElementTabSet>;
 template class LuaType<DataSource>;
 
 
+//reference counted types
+template<> bool LuaType<Element>::is_reference_counted() { return true; }
+template<> bool LuaType<Document>::is_reference_counted() { return true; }
+template<> bool LuaType<Event>::is_reference_counted() { return true; }
+template<> bool LuaType<Context>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementForm>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementFormControl>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementFormControlDataSelect>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementFormControlSelect>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementFormControlInput>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementFormControlTextArea>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementDataGrid>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementDataGridRow>::is_reference_counted() { return true; }
+template<> bool LuaType<ElementTabSet>::is_reference_counted() { return true; }
+/////////////////////////
+
 
 template<> void LuaType<rocket>::extra_init(lua_State* L, int metatable_index)
 {
@@ -206,7 +222,6 @@ template<> void LuaType<Document>::extra_init(lua_State* L, int metatable_index)
     LuaType<Element>::_regfunctions(L,metatable_index,metatable_index - 1);
 }
 
-
 template<> void LuaType<ElementStyle>::extra_init(lua_State* L, int metatable_index)
 {
     lua_pushcfunction(L,ElementStyle__index);
@@ -271,7 +286,6 @@ template<> void LuaType<ElementTabSet>::extra_init(lua_State* L, int metatable_i
     LuaType<Element>::_regfunctions(L,metatable_index,metatable_index-1);
 }
 
-
 template<> void LuaType<Log>::extra_init(lua_State* L, int metatable_index)
 {
     //due to they way that LuaType::Register is made, we know that the method table is at the index