ToluaUtils.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright (c) 2008-2022 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Core/Context.h"
  5. #ifdef _WIN32
  6. #include "../GraphicsAPI/IndexBuffer.h"
  7. #include "../GraphicsAPI/VertexBuffer.h"
  8. #endif
  9. struct lua_State;
  10. using namespace Urho3D;
  11. /// Check is String.
  12. #define tolua_isurho3dstring tolua_isstring
  13. /// Push String.
  14. #define tolua_pushurho3dstring(L, s) tolua_pushstring(L, s.CString()) // NOLINT(misc-macro-parentheses)
  15. /// Convert to String.
  16. const char* tolua_tourho3dstring(lua_State* L, int narg, const char* str);
  17. /// Convert to String.
  18. const char* tolua_tourho3dstring(lua_State* L, int narg, const String& str);
  19. /// Set context.
  20. void SetContext(lua_State* L, Context* context);
  21. /// Return context.
  22. Context* GetContext(lua_State* L);
  23. /// Create object.
  24. template <typename T> int ToluaNewObject(lua_State* tolua_S)
  25. {
  26. auto* object = Mtolua_new(T(GetContext(tolua_S)));
  27. tolua_pushusertype(tolua_S, (void*)object, T::GetTypeNameStatic().CString());
  28. return 1;
  29. }
  30. /// Create object with garbage collection.
  31. template <typename T> int ToluaNewObjectGC(lua_State* tolua_S)
  32. {
  33. auto* object = Mtolua_new(T(GetContext(tolua_S)));
  34. tolua_pushusertype(tolua_S, (void*)object, T::GetTypeNameStatic().CString());
  35. tolua_register_gc(tolua_S, lua_gettop(tolua_S));
  36. return 1;
  37. }
  38. /// Return subsystem.
  39. template <typename T> int ToluaGetSubsystem(lua_State* tolua_S)
  40. {
  41. T* subsystem = GetContext(tolua_S)->GetSubsystem<T>();
  42. tolua_pushusertype(tolua_S, (void*)subsystem, T::GetTypeNameStatic().CString());
  43. return 1;
  44. }
  45. /// Check is Vector<T>.
  46. template <typename T> int ToluaIsVector(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
  47. {
  48. return tolua_isusertypearray(L, lo, type, -1, def, err);
  49. }
  50. /// Convert to Vector<T>. This function is not thread-safe.
  51. template <typename T> void* ToluaToVector(lua_State* L, int narg, void* def)
  52. {
  53. if (!lua_istable(L, narg))
  54. return nullptr;
  55. static Vector<T> result;
  56. result.Clear();
  57. result.Resize((unsigned)lua_objlen(L, narg));
  58. for (unsigned i = 0; i < result.Size(); ++i)
  59. {
  60. lua_rawgeti(L, narg, i + 1); // Lua index starts from 1
  61. result[i] = *static_cast<T*>(tolua_tousertype(L, -1, def));
  62. lua_pop(L, 1);
  63. }
  64. return &result;
  65. }
  66. /// Push Vector<T> to Lua as a table.
  67. template <typename T> int ToluaPushVector(lua_State* L, void* data, const char* type)
  68. {
  69. lua_newtable(L);
  70. Vector<T>& vector = *static_cast<Vector<T>*>(data);
  71. for (unsigned i = 0; i < vector.Size(); ++i)
  72. {
  73. tolua_pushusertype(L, &vector[i], type);
  74. lua_rawseti(L, -2, i + 1);
  75. }
  76. return 1;
  77. }
  78. /// Check is PODVector<T>.
  79. template <typename T> int ToluaIsPODVector(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
  80. {
  81. // Whether it is POD or non-POD, on Lua side they are just usertype object, so we can reuse the same function
  82. return ToluaIsVector<T>(L, lo, type, def, err);
  83. }
  84. /// Check is PODVector<T, is_arithmetic<T>>. Use template function overload as non-type partial template specialization is not allowed.
  85. template <typename T> int ToluaIsPODVector(double /*overload*/, lua_State* L, int lo, const char* /*type*/, int def, tolua_Error* err)
  86. {
  87. return tolua_isnumberarray(L, lo, -1, def, err);
  88. }
  89. /// Convert to PODVector<T>. This function is not thread-safe.
  90. template <typename T> void* ToluaToPODVector(lua_State* L, int narg, void* def)
  91. {
  92. return ToluaToVector<T>(L, narg, def);
  93. }
  94. /// Convert to PODVector<T, is_arithmetic<T>>. This function is not thread-safe. Use template function overload as non-type partial template specialization is not allowed.
  95. template <typename T> void* ToluaToPODVector(double /*overload*/, lua_State* L, int narg, void* /*def*/)
  96. {
  97. if (!lua_istable(L, narg))
  98. return nullptr;
  99. static PODVector<T> result;
  100. result.Clear();
  101. result.Resize((unsigned)lua_objlen(L, narg));
  102. for (unsigned i = 0; i < result.Size(); ++i)
  103. {
  104. lua_rawgeti(L, narg, i + 1);
  105. result[i] = (T)tolua_tonumber(L, -1, 0);
  106. lua_pop(L, 1);
  107. }
  108. return &result;
  109. }
  110. /// Push PODVector<T> to Lua as a table.
  111. template <typename T> int ToluaPushPODVector(lua_State* L, void* data, const char* type)
  112. {
  113. return ToluaPushVector<T>(L, data, type);
  114. }
  115. /// Push PODVector<T, is_pointer<T>> to Lua as a table. Use template function overload as non-type partial template specialization is not allowed.
  116. template <typename T> int ToluaPushPODVector(const char* /*overload*/, lua_State* L, void* data, const char* type)
  117. {
  118. lua_newtable(L);
  119. const PODVector<T>& vector = *static_cast<const PODVector<T>*>(data);
  120. for (unsigned i = 0; i < vector.Size(); ++i)
  121. {
  122. tolua_pushusertype(L, vector[i], type);
  123. lua_rawseti(L, -2, i + 1);
  124. }
  125. return 1;
  126. }
  127. /// Push PODVector<T, is_arithmetic<T>> to Lua as a table. Use template function overload as non-type partial template specialization is not allowed.
  128. template <typename T> int ToluaPushPODVector(double /*overload*/, lua_State* L, void* data, const char* /*type*/)
  129. {
  130. lua_newtable(L);
  131. const PODVector<T>& vector = *static_cast<const PODVector<T>*>(data);
  132. for (unsigned i = 0; i < vector.Size(); ++i)
  133. {
  134. lua_pushnumber(L, vector[i]);
  135. lua_rawseti(L, -2, i + 1);
  136. }
  137. return 1;
  138. }
  139. // GCC and Clang does not follow the C++ standard in expecting explicit template specialization shall be declared before first use,
  140. // both compilers are able to avoid the multiple definitions of template instantiation symbol during linking by using weak symbol
  141. // MSVC and MinGW, however, follow the standard strictly, hence we need to declare all the explicit template specializations below
  142. // to keep these two compilers happy
  143. #ifdef _WIN32
  144. template <> int ToluaIsVector<String>(lua_State* L, int lo, const char* type, int def, tolua_Error* err);
  145. template <> void* ToluaToVector<String>(lua_State* L, int narg, void* def);
  146. template <> int ToluaPushVector<String>(lua_State* L, void* data, const char* type);
  147. template <> int ToluaIsPODVector<bool>(double /*overload*/, lua_State* L, int lo, const char* type, int def, tolua_Error* err);
  148. template <> void* ToluaToPODVector<bool>(double /*overload*/, lua_State* L, int narg, void* def);
  149. template <> int ToluaPushPODVector<bool>(double /*overload*/, lua_State* L, void* data, const char* type);
  150. template <> void* ToluaToVector<SharedPtr<IndexBuffer>>(lua_State* L, int narg, void* def);
  151. template <> void* ToluaToVector<SharedPtr<VertexBuffer>>(lua_State* L, int narg, void* def);
  152. #endif
  153. /// Convert object at the given index and store it in Variant. This function is not thread-safe.
  154. void ToluaToVariant(lua_State* L, int narg, void* def, Variant& variant);
  155. /// Push object stored in a Variant to stack. Empty variant value is pushed as nil.
  156. void ToluaPushVariant(lua_State* L, const Variant* variant, const char* type = nullptr);
  157. /// Push a registered Lua user type to stack. If the specified type is not yet registered, a nil is pushed instead.
  158. void ToluaPushRegisteredUserType(lua_State* L, void* data, const char* type);
  159. /// Push Object to Lua.
  160. void ToluaPushObject(lua_State* L, void* data, const char* type);