]> git.sesse.net Git - nageru/blob - nageru/lua_utils.h
Fix a comment typo.
[nageru] / nageru / lua_utils.h
1 #ifndef _LUA_UTILS_H
2 #define _LUA_UTILS_H 1
3
4 #include <lauxlib.h>
5 #include <lua.hpp>
6
7 #include <mutex>
8 #include <utility>
9
10 class LuaRefWithDeleter {
11 public:
12         LuaRefWithDeleter(std::mutex *m, lua_State *L, int ref) : m(m), L(L), ref(ref) {}
13         ~LuaRefWithDeleter() {
14                 std::lock_guard<std::mutex> lock(*m);
15                 luaL_unref(L, LUA_REGISTRYINDEX, ref);
16         }
17         int get() const { return ref; }
18
19 private:
20         LuaRefWithDeleter(const LuaRefWithDeleter &) = delete;
21
22         std::mutex *m;
23         lua_State *L;
24         int ref;
25 };
26
27 template<class T, class... Args>
28 int wrap_lua_object(lua_State* L, const char *class_name, Args&&... args)
29 {
30         // Construct the C++ object and put it on the stack.
31         void *mem = lua_newuserdata(L, sizeof(T));
32         new(mem) T(std::forward<Args>(args)...);
33
34         // Look up the metatable named <class_name>, and set it on the new object.
35         luaL_getmetatable(L, class_name);
36         lua_setmetatable(L, -2);
37
38         return 1;
39 }
40
41 // Like wrap_lua_object, but the object is not owned by Lua; ie. it's not freed
42 // by Lua GC. This is typically the case for Effects, which are owned by EffectChain
43 // and expected to be destructed by it. The object will be of type T** instead of T*
44 // when exposed to Lua.
45 //
46 // Note that we currently leak if you allocate an Effect in this way and never call
47 // add_effect. We should see if there's a way to e.g. set __gc on it at construction time
48 // and then release that once add_effect() takes ownership.
49 template<class T, class... Args>
50 int wrap_lua_object_nonowned(lua_State* L, const char *class_name, Args&&... args)
51 {
52         // Construct the pointer ot the C++ object and put it on the stack.
53         T **obj = (T **)lua_newuserdata(L, sizeof(T *));
54         *obj = new T(std::forward<Args>(args)...);
55
56         // Look up the metatable named <class_name>, and set it on the new object.
57         luaL_getmetatable(L, class_name);
58         lua_setmetatable(L, -2);
59
60         return 1;
61 }
62
63 template<class T>
64 int wrap_lua_existing_object_nonowned(lua_State* L, const char *class_name, T *ptr)
65 {
66         // Construct the pointer ot the C++ object and put it on the stack.
67         T **obj = (T **)lua_newuserdata(L, sizeof(T *));
68         *obj = ptr;
69
70         // Look up the metatable named <class_name>, and set it on the new object.
71         luaL_getmetatable(L, class_name);
72         lua_setmetatable(L, -2);
73
74         return 1;
75 }
76
77 #endif  // !defined(_LUA_UTILS_H)