LuaBinder.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Script/Common.h>
  7. #include <AnKi/Util/Assert.h>
  8. #include <AnKi/Util/StdTypes.h>
  9. #include <AnKi/Util/String.h>
  10. #include <AnKi/Util/Functions.h>
  11. #include <AnKi/Util/HashMap.h>
  12. #include <Lua/lua.hpp>
  13. #ifndef ANKI_LUA_HPP
  14. # error "Wrong LUA header included"
  15. #endif
  16. namespace anki {
  17. // Forward
  18. class LuaUserData;
  19. #define ANKI_LUA_ERROR() luaL_error(l, "Glue error at: " ANKI_FILE ":" ANKI_STRINGIZE(__LINE__) " %s", ANKI_FUNC)
  20. #define ANKI_LUA_ERROR_MSG(message) luaL_error(l, "Glue error: " message " (" ANKI_FILE ":" ANKI_STRINGIZE(__LINE__) " %s)", ANKI_FUNC)
  21. using LuaUserDataSerializeCallback = void (*)(LuaUserData& self, void* data, PtrSize& size);
  22. using LuaUserDataDeserializeCallback = void (*)(const void* data, LuaUserData& self);
  23. class LuaUserDataTypeInfo
  24. {
  25. public:
  26. I64 m_signature;
  27. const char* m_typeName;
  28. PtrSize m_structureSize;
  29. LuaUserDataSerializeCallback m_serializeCallback;
  30. LuaUserDataDeserializeCallback m_deserializeCallback;
  31. };
  32. // LUA userdata.
  33. class LuaUserData
  34. {
  35. public:
  36. // Note: NEVER ADD A DESTRUCTOR. LUA cannot call that.
  37. ~LuaUserData() = delete;
  38. I64 getSig() const
  39. {
  40. return m_sig;
  41. }
  42. void initGarbageCollected(const LuaUserDataTypeInfo* info)
  43. {
  44. ANKI_ASSERT(info);
  45. m_sig = info->m_signature;
  46. m_info = info;
  47. m_addressOrGarbageCollect = kGarbageCollectedMagic;
  48. }
  49. // Note: Accepting const void* is wrong because getData returns a mutable pointer. Fix that.
  50. void initPointed(const LuaUserDataTypeInfo* info, const void* ptrToObject)
  51. {
  52. ANKI_ASSERT(info);
  53. m_sig = info->m_signature;
  54. m_info = info;
  55. const U64 addr = ptrToNumber(ptrToObject);
  56. ANKI_ASSERT(addr != kGarbageCollectedMagic && "Can't use this address");
  57. m_addressOrGarbageCollect = addr;
  58. }
  59. Bool isGarbageCollected() const
  60. {
  61. ANKI_ASSERT(m_addressOrGarbageCollect != 0);
  62. return m_addressOrGarbageCollect == kGarbageCollectedMagic;
  63. }
  64. template<typename T>
  65. T* getData()
  66. {
  67. ANKI_ASSERT(m_addressOrGarbageCollect != 0);
  68. ANKI_ASSERT(getDataTypeInfoFor<T>().m_signature == m_sig);
  69. T* out = nullptr;
  70. if(isGarbageCollected())
  71. {
  72. // Garbage collected, the data -in memory- are after this object
  73. PtrSize mem = ptrToNumber(this);
  74. mem += getAlignedRoundUp(alignof(T), sizeof(LuaUserData));
  75. out = numberToPtr<T*>(mem);
  76. }
  77. else
  78. {
  79. // Pointed
  80. PtrSize mem = static_cast<PtrSize>(m_addressOrGarbageCollect);
  81. out = numberToPtr<T*>(mem);
  82. }
  83. ANKI_ASSERT(out);
  84. ANKI_ASSERT(isAligned(alignof(T), out));
  85. return out;
  86. }
  87. template<typename T>
  88. static PtrSize computeSizeForGarbageCollected()
  89. {
  90. return getAlignedRoundUp(alignof(T), sizeof(LuaUserData)) + sizeof(T);
  91. }
  92. const LuaUserDataTypeInfo& getDataTypeInfo() const
  93. {
  94. ANKI_ASSERT(m_info);
  95. return *m_info;
  96. }
  97. template<typename TWrapedType>
  98. static const LuaUserDataTypeInfo& getDataTypeInfoFor();
  99. private:
  100. static constexpr U64 kGarbageCollectedMagic = 0xFAFC0FEEDEADB1FF;
  101. I64 m_sig = 0; ///< Signature to identify the user data.
  102. U64 m_addressOrGarbageCollect = 0; ///< Encodes an address or a special address if it's for garbage collection.
  103. const LuaUserDataTypeInfo* m_info = nullptr;
  104. };
  105. class LuaBinderSerializeGlobalsCallback
  106. {
  107. public:
  108. virtual void write(const void* data, PtrSize dataSize) = 0;
  109. };
  110. // Lua binder class. A wrapper on top of LUA
  111. class LuaBinder
  112. {
  113. public:
  114. LuaBinder();
  115. LuaBinder(const LuaBinder&) = delete; // Non-copyable
  116. ~LuaBinder();
  117. LuaBinder& operator=(const LuaBinder&) = delete; // Non-copyable
  118. lua_State* getLuaState()
  119. {
  120. ANKI_ASSERT(m_l);
  121. return m_l;
  122. }
  123. // Expose a variable to the lua state
  124. template<typename T>
  125. static void exposeVariable(lua_State* state, CString name, T* y)
  126. {
  127. void* ptr = lua_newuserdata(state, sizeof(LuaUserData));
  128. LuaUserData* ud = static_cast<LuaUserData*>(ptr);
  129. ud->initPointed(&LuaUserData::getDataTypeInfoFor<T>(), y);
  130. luaL_setmetatable(state, LuaUserData::getDataTypeInfoFor<T>().m_typeName);
  131. lua_setglobal(state, name.cstr());
  132. }
  133. template<typename T>
  134. static void pushVariableToTheStack(lua_State* state, T* y)
  135. {
  136. void* ptr = lua_newuserdata(state, sizeof(LuaUserData));
  137. LuaUserData* ud = static_cast<LuaUserData*>(ptr);
  138. ud->initPointed(&LuaUserData::getDataTypeInfoFor<T>(), y);
  139. luaL_setmetatable(state, LuaUserData::getDataTypeInfoFor<T>().m_typeName);
  140. }
  141. // Evaluate a string
  142. static Error evalString(lua_State* state, const CString& str);
  143. static void garbageCollect(lua_State* state)
  144. {
  145. lua_gc(state, LUA_GCCOLLECT, 0);
  146. }
  147. // For debugging purposes
  148. static void stackDump(lua_State* l);
  149. // Create a new LUA class
  150. static void createClass(lua_State* l, const LuaUserDataTypeInfo* typeInfo);
  151. // Add new function in a class that it's already in the stack
  152. static void pushLuaCFuncMethod(lua_State* l, const char* name, lua_CFunction luafunc);
  153. // Add a new static function in the class.
  154. static void pushLuaCFuncStaticMethod(lua_State* l, const char* className, const char* name, lua_CFunction luafunc);
  155. // Add a new function.
  156. static void pushLuaCFunc(lua_State* l, const char* name, lua_CFunction luafunc);
  157. // Dump global variables.
  158. static void serializeGlobals(lua_State* l, LuaBinderSerializeGlobalsCallback& callback);
  159. // Deserialize global variables.
  160. static void deserializeGlobals(lua_State* l, const void* data, PtrSize dataSize);
  161. // Make sure that the arguments match the argsCount number
  162. static Error checkArgsCount(lua_State* l, const Char* file, U32 line, const Char* func, I argsCount);
  163. // Get a number from the stack.
  164. template<typename TNumber>
  165. static Error checkNumber(lua_State* l, const Char* file, U32 line, const Char* func, I32 stackIdx, TNumber& number)
  166. {
  167. lua_Number lnum;
  168. Error err = checkNumberInternal(l, file, line, func, stackIdx, lnum);
  169. if(!err)
  170. {
  171. number = TNumber(lnum);
  172. }
  173. return err;
  174. }
  175. // Get a string from the stack.
  176. static Error checkString(lua_State* l, const Char* file, U32 line, const Char* func, I32 stackIdx, const char*& out);
  177. // Get some user data from the stack.
  178. // The function uses the type signature to validate the type and not the
  179. // typeName. That is supposed to be faster.
  180. static Error checkUserData(lua_State* l, const Char* file, U32 line, const Char* func, I32 stackIdx, const LuaUserDataTypeInfo& typeInfo,
  181. LuaUserData*& out);
  182. private:
  183. lua_State* m_l = nullptr;
  184. ScriptHashMap<I64, const LuaUserDataTypeInfo*> m_userDataSigToDataInfo;
  185. static void* luaAllocCallback(void* userData, void* ptr, PtrSize osize, PtrSize nsize);
  186. static Error checkNumberInternal(lua_State* l, const Char* file, U32 line, const Char* func, I32 stackIdx, lua_Number& number);
  187. };
  188. } // end namespace anki