SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
LUA.h
Go to the documentation of this file.
1 
5 #pragma once
6 
7 #include "common/Types.h"
8 #include "common/NonCopyable.h"
9 // TODO: redefine these
10 //lua_writestring
11 //lua_writeline
12 //lua_writestringerror
13 #include <lua.hpp>
14 #include <string>
15 #include <map>
16 
17 namespace ai {
18 
19 namespace lua {
20 
21 namespace {
22 const std::string META_PREFIX = "META_";
23 
24 int panicCB(lua_State *L) {
25  ai_log_error("Lua panic. Error message: %s", (lua_isnil(L, -1) ? "" : lua_tostring(L, -1)));
26  return 0;
27 }
28 
29 }
30 
31 class LUAType {
32 private:
33  lua_State* _state;
34 public:
35  LUAType(lua_State* state, const std::string& name) :
36  _state(state) {
37  const std::string metaTable = META_PREFIX + name;
38  luaL_newmetatable(_state, metaTable.c_str());
39  lua_pushvalue(_state, -1);
40  lua_setfield(_state, -2, "__index");
41  }
42 
43  // only non-capturing lambdas can be converted to function pointers
44  template<class FUNC>
45  void addFunction(const std::string& name, FUNC&& func) {
46  lua_pushcfunction(_state, func);
47  lua_setfield(_state, -2, name.c_str());
48  }
49 
50  void addValue(const char* name, const char* value) {
51  lua_pushstring(_state, value);
52  lua_setfield(_state, -2, name);
53  }
54 };
55 
65 class LUA : public NonCopyable {
66 private:
67  lua_State *_state;
68  std::string _error;
69  bool _destroy;
70 
71 public:
72  explicit LUA(lua_State *state) :
73  _state(state), _destroy(false) {
74  }
75 
76  explicit LUA(bool debug = false) :
77  _state(luaL_newstate()), _destroy(true) {
78  luaL_openlibs(_state);
79  lua_atpanic(_state, panicCB);
80  lua_gc(_state, LUA_GCSTOP, 0);
81  }
82 
83  ~LUA () {
84  if (_destroy) {
85  //const int bytes = lua_gc(_state, LUA_GCCOUNT, 0) * 1024 + lua_gc(_state, LUA_GCCOUNTB, 0);
86  lua_gc(_state, LUA_GCRESTART, 0);
87  lua_close(_state);
88  }
89  _state = nullptr;
90  }
91 
92  inline lua_State* getState () const {
93  return _state;
94  }
95 
96  template<class T>
97  inline T* newGlobalData (const std::string& prefix, T *userData) const {
98  lua_pushlightuserdata(_state, userData);
99  lua_setglobal(_state, prefix.c_str());
100  return userData;
101  }
102 
103  template<class T>
104  static T* getGlobalData(lua_State *L, const std::string& prefix) {
105  lua_getglobal(L, prefix.c_str());
106  T* data = (T*) lua_touserdata(L, -1);
107  lua_pop(L, 1);
108  return data;
109  }
110 
111  template<class T>
112  static T* newUserdata(lua_State *L, const std::string& prefix, T* data) {
113  T ** udata = (T **) lua_newuserdata(L, sizeof(T *));
114  const std::string name = META_PREFIX + prefix;
115  luaL_getmetatable(L, name.c_str());
116  lua_setmetatable(L, -2);
117  *udata = data;
118  return data;
119  }
120 
121  template<class T>
122  static T* getUserData (lua_State *L, int n, const std::string& prefix) {
123  const std::string name = META_PREFIX + prefix;
124  return *(T **) luaL_checkudata(L, n, name.c_str());
125  }
126 
127  static int returnError (lua_State *L, const std::string& error) {
128  ai_log_error("LUA error: '%s'", error.c_str());
129  return luaL_error(L, "%s", error.c_str());
130  }
131 
132  void reg (const std::string& prefix, luaL_Reg* funcs) {
133  const std::string metaTableName = META_PREFIX + prefix;
134  luaL_newmetatable(_state, metaTableName.c_str());
135  luaL_setfuncs(_state, funcs, 0);
136  lua_pushvalue(_state, -1);
137  lua_setfield(_state, -1, "__index");
138  lua_setglobal(_state, prefix.c_str());
139  }
140 
141  LUAType registerType (const std::string& name) {
142  return LUAType(_state, name);
143  }
144 
145  void setError (const std::string& errorStr) {
146  _error = errorStr;
147  }
148 
149  const std::string& error () const {
150  return _error;
151  }
152 
153  bool load (const std::string &luaString) {
154  return load(luaString.c_str(), luaString.length());
155  }
156 
157  bool load (const char *luaString, size_t len) {
158  if (luaL_loadbufferx(_state, luaString, len, "", nullptr) || lua_pcall(_state, 0, LUA_MULTRET, 0)) {
159  setError(lua_tostring(_state, -1));
160  lua_pop(_state, 1);
161  return false;
162  }
163 
164  return true;
165  }
166 
170  bool execute (const std::string &function, int returnValues = 0) {
171  lua_getglobal(_state, function.c_str());
172  const int ret = lua_pcall(_state, 0, returnValues, 0);
173  if (ret != 0) {
174  setError(lua_tostring(_state, -1));
175  return false;
176  }
177 
178  return true;
179  }
180 };
181 
182 }
183 
184 }
#define ai_log_error(...)
Logging macro to provide your own loggers.
Definition: Types.h:23
bool execute(const std::string &function, int returnValues=0)
Definition: LUA.h:170
Definition: LUA.h:31
Definition: LUA.h:65
Definition: NonCopyable.h:8