[Orxonox-commit 6931] r11552 - code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller

kohlia at orxonox.net kohlia at orxonox.net
Tue Nov 7 19:26:12 CET 2017


Author: kohlia
Date: 2017-11-07 19:26:12 +0100 (Tue, 07 Nov 2017)
New Revision: 11552

Modified:
   code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb.ipp
   code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.cc
   code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.h
   code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc
   code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc
Log:
Lua bindings should work now



Modified: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb.ipp
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb.ipp	2017-11-07 16:47:14 UTC (rev 11551)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb.ipp	2017-11-07 18:26:12 UTC (rev 11552)
@@ -44,7 +44,6 @@
             std::cerr << "ERROR: LuaTB: Lua script called a function with wrong number of arguments (" << argc << " given, " << sizeof...(Args) << " expected)" << std::endl;
             return LUA_ERRSYNTAX;
         }
-        orxonox::orxout(orxonox::user_warning) << "what" << std::endl;
 
         // Call getArgument for every argument seperately to convert each argument
         // to the correct type and call the function afterwards

Modified: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.cc	2017-11-07 16:47:14 UTC (rev 11551)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.cc	2017-11-07 18:26:12 UTC (rev 11552)
@@ -3,18 +3,21 @@
 #include "luatb.h"
 #include <string>
 
+// Holds a list of all current callback references
+std::list<std::unique_ptr<int> > LuaTBTypedStack::callbackRefs = {};
+
 // Explicit and full specializations need to be in a .cpp file
 
 template<>
-int LuaTBTypedStack::popFromLuaStack<int>(lua_State *lua)
+int LuaTBTypedStack::getFromLuaStack<int>(lua_State *lua)
 { return lua_tointeger(lua, lua_gettop(lua)); }
 
 template<>
-double LuaTBTypedStack::popFromLuaStack<double>(lua_State *lua)
+double LuaTBTypedStack::getFromLuaStack<double>(lua_State *lua)
 { return lua_tonumber(lua, lua_gettop(lua)); }
 
 template<>
-std::string LuaTBTypedStack::popFromLuaStack<std::string>(lua_State *lua)
+std::string LuaTBTypedStack::getFromLuaStack<std::string>(lua_State *lua)
 { return lua_tostring(lua, lua_gettop(lua)); }
 
 template<>

Modified: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.h
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.h	2017-11-07 16:47:14 UTC (rev 11551)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/luatb_typed_stack.h	2017-11-07 18:26:12 UTC (rev 11552)
@@ -13,71 +13,77 @@
 class LuaTBTypedStack
 {
 public:
-    // Get an argument from the lua stack and convert it to type 'T'
+
+    // Get a non-function argument from the lua stack and convert it to type 'T'
+    // Pops the value from the stack.
     template<typename T>
-    static T getArgument(lua_State *lua)
+    static typename std::enable_if<!IsCallable<T>::value, T>::type getArgument(lua_State *lua)
     {
-        T value = LuaTBTypedStack::popFromLuaStack<T>(lua);
+        T value = LuaTBTypedStack::getFromLuaStack<T>(lua);
         lua_pop(lua, 1);
         return value;
     }
 
-private:
-    // Gets the top element of the lua stack and converts it to the appropriate
-    // type. Only works for certain types, if 'T' is none of these types, you'll
-    // get an error.
-    template<typename T>
-    static typename std::enable_if<!IsCallable<T>::value, T>::type popFromLuaStack(lua_State *lua);
-
     // Specialization if 'T' is a callable type (std::function). Saves the lua
     // function in the registry and constructs a function to call it again.
     // 'decltype(&T::operator())' represents the function signature of the callable
     // object.
     template<typename T>
-    static typename std::enable_if<IsCallable<T>::value, T>::type popFromLuaStack(lua_State *lua)
+    static typename std::enable_if<IsCallable<T>::value, T>::type getArgument(lua_State *lua)
     {
-        return GetLuaCallback<decltype(&T::operator())>::value(lua, luaL_ref(lua, LUA_REGISTRYINDEX));
+        // Here's the tricky part. Apparently, references in the registry can only
+        // be called once. This is why we always have to re-add it to the registry
+        // after every call. That means, we need a persistent variable for 'ref' and
+        // that's only possible with a pointer in this case.
+        int *ref = new int(luaL_ref(lua, LUA_REGISTRYINDEX));
+        LuaTBTypedStack::callbackRefs.push_back(std::unique_ptr<int>(ref));
+
+        return GetLuaCallback<decltype(&T::operator())>::value(lua, ref);
     }
 
-    // Get a function that will call a lua callback
+private:
     template<typename T> struct GetLuaCallback;
 
+    // Gets a value from the top of the lua stack and returns it with the proper type.
+    // Does not pop the value!
+    template<typename T> static T getFromLuaStack(lua_State *lua);
+
     // This class is only valid for std::function types. The type argument will not
     // be a normal function signature because it is the signature of
     // std::function<>::operator(), which is also the reason for the 'const'.
     template<typename Ret, typename... Args>
-    struct GetLuaCallback<Ret(std::function<Ret(Args...)>::*)(Args...) const>
+    struct GetLuaCallback<void (std::function<Ret(Args...)>::*)(Args...) const>
     {
         // Returns a lambda that will push the arguments to the lua stack and call
         // the function afterwards. We can't return 'callLuaFunction' directly,
         // because we need the additional arguments 'lua' and 'ref' which we would
         // like to hide from the user.
-        static std::function<Ret (Args...)> value(lua_State *lua, int ref)
+        static std::function<void (Args...)> value(lua_State *lua, int *ref)
         {
-            orxonox::orxout(orxonox::user_warning) << "Ref1: " << ref << std::endl;
-            return [lua, ref](Args... args){return callLuaFunction<Ret, Args...>(lua, ref, args...);};
+            return [lua, ref](Args... args){callLuaFunction<Ret, Args...>(lua, ref, args...);};
         }
     };
 
     // Pushes all arguments to the lua stack and calls a lua function afterwards
     template<typename Ret, typename... Args>
-    static Ret callLuaFunction(lua_State *lua, int ref, Args... args)
+    static void callLuaFunction(lua_State *lua, int *ref, Args... args)
     {
-        lua_rawgeti(lua, LUA_REGISTRYINDEX, ref);
+        // Get the value of the callback from the registry and push it to the stack
+        lua_rawgeti(lua, LUA_REGISTRYINDEX, *ref);
+
+        // Duplicate it on the stack so we can save it in the registry again after
+        // we called the callback.
+        lua_pushvalue(lua, 1);
+
         // We pass one extra argument in case the function has no arguments at all
         pushArgumentsToLuaStack<Args...>(lua, args..., false);
-        int r = lua_pcall(lua, 1, sizeof...(args), 0);
+        lua_pcall(lua, sizeof...(args), 0, 0);
 
-        orxonox::orxout(orxonox::user_warning) << "Ref2: " << ref << std::endl;
-if(r != 0){
-        const char* message = lua_tostring(lua, -1);
-        std::cout << message << std::endl;
-        lua_pop(lua, 1);
-}
+        // Release the old reference and save the function in the registry again
+        lua_unref(lua, *ref);
+        *ref = luaL_ref(lua, LUA_REGISTRYINDEX);
+    }
 
-        // TODO
-        return Ret();
-    }
     // This is needed in case the function has no arguments at all. Otherwise, we
     // would have a missing argument for such function. This is also why we pass
     // a dummy argument in 'callLuaFunction', so we have at least one argument.
@@ -96,6 +102,8 @@
     // Pushes a value to the lua stack. Only the specializations are valid.
     template<typename T>
     static void pushToLuaStack(lua_State *lua, T value);
+
+    static std::list<std::unique_ptr<int> > callbackRefs;
 };
 
 #endif // LUATB_TYPED_STACK_H

Modified: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc	2017-11-07 16:47:14 UTC (rev 11551)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc	2017-11-07 18:26:12 UTC (rev 11552)
@@ -81,8 +81,6 @@
 void ScriptableController::registerTimeout(std::function<void ()> callback, double timeout)
 {
     this->timeouts.push_back(std::make_pair(callback, static_cast<float>(timeout)));
-    orxout(user_warning) << "Calling should work..." << std::endl;
-    callback();
 }
 
 void ScriptableController::tick(float dt)
@@ -94,7 +92,6 @@
         timeout->second -= dt;
         if(timeout->second <= 0)
         {
-            orxout(user_warning) << "Calling..." << std::endl;
             timeout->first();
             timeout = this->timeouts.erase(timeout);
         }

Modified: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc	2017-11-07 16:47:14 UTC (rev 11551)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc	2017-11-07 18:26:12 UTC (rev 11552)
@@ -1,7 +1,5 @@
 
 #include "scriptable_controller_api.h"
-#include <chrono>
-#include "lua.hpp"
 #include "luatb.h"
 #include "scriptable_controller.h"
 
@@ -29,12 +27,13 @@
 
 void ScriptableControllerAPI::registerAfterTimeout(std::function<void (void)> callback, double timeout)
 {
+    // TODO Extend timer class to accept std::function
     this->controller_->registerTimeout(callback, timeout);
 }
 
 int ScriptableControllerAPI::registerAtNearObject(std::function<void (int, int)> callback, int obj1, int obj2, double distance)
 {
-    orxout(user_warning) << "Working!" << std::endl;
+
 }
 
 int ScriptableControllerAPI::registerAtAreaEnter(std::function<void (int)> callback, int obj, int x, int y, int z, int dx, int dy, int dz)



More information about the Orxonox-commit mailing list