From 520dcf8cdf0e6cf36210fa7826b63fe2c64ec218 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 18 Jul 2016 23:30:20 +0200 Subject: [PATCH] rework lua-bridge C++ variable references Since lua functions are closures, C++ methods that pass arguments by reference cannot be used directly. The previous approach (boost::ref) failed with clang. Assume the following: void foo (float&) { } static inline float& bar () { boost::reference_wrapper r (42); return r.get (); } foo ( bar () ); With gcc, "r" goes out of scope after foo's arguments are processed and all is well. But with clang, "r" already leave scope when *inlined* bar() returns. Solution: allocate some user-data on the lua-stack to hold the reference. There is no reference to this user-data so lua will eventually garbage collect it. (theoretically, creating the table which holds the return-values could trigger an emergency garbage collection when memory is low and free the reference just while they're being pushed to the table, then gain FuncArgs already dereferenced them all as variable on the C stack -- probably again compiler specific) --- libs/lua/LuaBridge/LuaBridge.h | 1 - libs/lua/LuaBridge/detail/Stack.h | 53 +++++++++++++++---------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/libs/lua/LuaBridge/LuaBridge.h b/libs/lua/LuaBridge/LuaBridge.h index 706e77cbfd..01f9e90b7d 100644 --- a/libs/lua/LuaBridge/LuaBridge.h +++ b/libs/lua/LuaBridge/LuaBridge.h @@ -47,7 +47,6 @@ #include #include -#include #include #include diff --git a/libs/lua/LuaBridge/detail/Stack.h b/libs/lua/LuaBridge/detail/Stack.h index 0d4919be27..e6ff637f19 100644 --- a/libs/lua/LuaBridge/detail/Stack.h +++ b/libs/lua/LuaBridge/detail/Stack.h @@ -127,8 +127,8 @@ struct Stack static inline int& get (lua_State* L, int index) { int l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + int* x = new (lua_newuserdata (L, sizeof (int))) int (l); + return *x; } }; @@ -175,8 +175,8 @@ struct Stack static inline unsigned int& get (lua_State* L, int index) { unsigned int l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + unsigned int* x = new (lua_newuserdata (L, sizeof (unsigned int))) unsigned int (l); + return *x; } }; @@ -223,8 +223,8 @@ struct Stack static inline unsigned char& get (lua_State* L, int index) { unsigned char l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + unsigned char* x = new (lua_newuserdata (L, sizeof (unsigned char))) unsigned char (l); + return *x; } }; @@ -271,8 +271,8 @@ struct Stack static inline short& get (lua_State* L, int index) { short l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + short* x = new (lua_newuserdata (L, sizeof (short))) short (l); + return *x; } }; @@ -319,8 +319,8 @@ struct Stack static inline unsigned short& get (lua_State* L, int index) { unsigned short l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + unsigned short* x = new (lua_newuserdata (L, sizeof (unsigned short))) unsigned short (l); + return *x; } }; @@ -367,8 +367,8 @@ struct Stack static inline long& get (lua_State* L, int index) { long l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + long* x = new (lua_newuserdata (L, sizeof (long))) long (l); + return *x; } }; @@ -415,8 +415,8 @@ struct Stack static inline unsigned long& get (lua_State* L, int index) { unsigned long l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + unsigned long* x = new (lua_newuserdata (L, sizeof (unsigned long))) unsigned long (l); + return *x; } }; @@ -463,8 +463,8 @@ struct Stack static inline long long& get (lua_State* L, int index) { long long l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + long long* x = new (lua_newuserdata (L, sizeof (long long))) long long (l); + return *x; } }; @@ -543,8 +543,8 @@ struct Stack static inline float& get (lua_State* L, int index) { float l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + float* x = new (lua_newuserdata (L, sizeof (float))) float (l); + return *x; } }; @@ -588,8 +588,8 @@ template <> struct Stack static inline double& get (lua_State* L, int index) { double l = static_cast (luaL_checknumber (L, index)); - boost::reference_wrapper r (l); - return r.get(); + double* x = new (lua_newuserdata (L, sizeof (double))) double (l); + return *x; } }; @@ -633,8 +633,8 @@ struct Stack { static inline bool& get (lua_State* L, int index) { bool l = lua_toboolean (L, index) ? true : false; - boost::reference_wrapper r (l); - return r.get(); + bool* x = new (lua_newuserdata (L, sizeof (bool))) bool (l); + return *x; } }; @@ -701,8 +701,8 @@ struct Stack static inline char get (lua_State* L, int index) { char l = luaL_checkstring (L, index) [0]; - boost::reference_wrapper r (l); - return r.get(); + char* x = new (lua_newuserdata (L, sizeof (char))) char (l); + return *x; } }; @@ -754,8 +754,7 @@ struct Stack { size_t len; const char *str = luaL_checklstring(L, index, &len); - std::string l (str, len); - boost::reference_wrapper r (l); - return r.get(); + std::string* x = new (lua_newuserdata (L, sizeof (std::string))) std::string (str, len); + return *x; } };