]> git.r.bdr.sh - rbdr/pico-engine/blob - LuaScript.cpp
Update project so it compiles
[rbdr/pico-engine] / LuaScript.cpp
1 // ---------------------------------------------------------------------------
2 // FILE NAME : LuaScript.cpp
3 // ---------------------------------------------------------------------------
4 // DESCRIPTION :
5 //
6 // Simple debugging routines
7 //
8 // ---------------------------------------------------------------------------
9 // VERSION : 1.00
10 // DATE : 1-Sep-2005
11 // AUTHOR : Richard Shephard
12 // ---------------------------------------------------------------------------
13 // LIBRARY INCLUDE FILES
14 #include <assert.h>
15 #include "luainc.h"
16 #include "luascript.h"
17 #include "luarestorestack.h"
18 #include "luathis.h"
19 // ---------------------------------------------------------------------------
20
21 #define BEGIN_LUA_CHECK(vm) lua_State *state = (lua_State *) vm; \
22 if (vm.Ok ()) {
23 #define END_LUA_CHECK }
24
25
26 //============================================================================
27 // int LuaCallback
28 //---------------------------------------------------------------------------
29 // Lua C-API calling that figures out which object to hand over to
30 //
31 // Parameter Dir Description
32 // --------- --- -----------
33 // lua IN State variable
34 //
35 // Return
36 // ------
37 // Number of return varaibles on the stack
38 //
39 // Comments
40 // --------
41 // This is the function lua calls for each C-Function that is
42 // registered with lua. At the time of registering the function
43 // with lua, we make lua record the method "number" so we can
44 // know what method was actually called. The lua stack is the
45 // following structure:
46 // 0: 'this' (table)
47 // 1 - ...: parameters passed in
48 //
49 //============================================================================
50 static int LuaCallback (lua_State *lua)
51 {
52 // Locate the psudo-index for the function number
53 int iNumberIdx = lua_upvalueindex (1);
54 int nRetsOnStack = 0;
55
56 bool fSuccess = false;
57
58 // Check for the "this" table
59 if (lua_istable (lua, 1))
60 {
61 // Found the "this" table. The object pointer is at the index 0
62 lua_rawgeti (lua, 1, 0);
63
64 if (lua_islightuserdata (lua, -1))
65 {
66 // Found the pointer, need to cast it
67 CLuaScript *pThis = (CLuaScript *) lua_touserdata (lua, -1);
68
69 // Get the method index
70 int iMethodIdx = (int) lua_tonumber (lua, iNumberIdx);
71
72 // Check that the method is correct index
73 assert (!(iMethodIdx > pThis->methods ()));
74
75 // Reformat the stack so our parameters are correct
76 // Clean up the "this" table
77 lua_remove (lua, 1);
78 // Clean up the pThis pointer
79 lua_remove (lua, -1);
80
81 // Call the class
82 nRetsOnStack = pThis->ScriptCalling (pThis->vm (), iMethodIdx);
83
84 fSuccess = true;
85 }
86 }
87
88 if (fSuccess == false)
89 {
90 lua_pushstring (lua, "LuaCallback -> Failed to call the class function");
91 lua_error (lua);
92 }
93
94 // Number of return variables
95 return nRetsOnStack;
96 }
97
98
99 //============================================================================
100 // CLuaScript::CLuaScript
101 //---------------------------------------------------------------------------
102 // Constructor. Sets up the lua stack and the "this" table
103 //
104 // Parameter Dir Description
105 // --------- --- -----------
106 // CLuaVirtualMachine IN VM to run on
107 //
108 // Return
109 // ------
110 // None.
111 //
112 //============================================================================
113 CLuaScript::CLuaScript (CLuaVirtualMachine& vm)
114 : m_vm (vm), m_nMethods (0), m_iThisRef (0), m_nArgs (0)
115 {
116 BEGIN_LUA_CHECK (vm)
117 // Create a reference to the "this" table. Each reference is unique
118 lua_newtable (state);
119 m_iThisRef = luaL_ref (state, LUA_REGISTRYINDEX);
120
121 // Save the "this" table to index 0 of the "this" table
122 CLuaRestoreStack rs (vm);
123 lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef);
124 lua_pushlightuserdata (state, (void *) this);
125 lua_rawseti (state, -2, 0);
126 END_LUA_CHECK
127 }
128
129 //============================================================================
130 // CLuaScript::~CLuaScript
131 //---------------------------------------------------------------------------
132 // Destructor
133 //
134 // Parameter Dir Description
135 // --------- --- -----------
136 // None.
137 //
138 // Return
139 // ------
140 // None.
141 //
142 //============================================================================
143 CLuaScript::~CLuaScript (void)
144 {
145 CLuaRestoreStack rs (m_vm);
146
147 BEGIN_LUA_CHECK (m_vm)
148 // Get the reference "this" table
149 lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef);
150
151 // Clear index 0
152 lua_pushnil (state);
153 lua_rawseti (state, -2, 0);
154 END_LUA_CHECK
155
156 }
157
158 //============================================================================
159 // bool CLuaScript::CompileBuffer
160 //---------------------------------------------------------------------------
161 // Compiles a given buffer
162 //
163 // Parameter Dir Description
164 // --------- --- -----------
165 // pbBuffer IN Data buffer
166 // szLen IN Length of buffer
167 //
168 // Return
169 // ------
170 // Success
171 //
172 //============================================================================
173 bool CLuaScript::CompileBuffer (unsigned char *pbBuffer, size_t szLen)
174 {
175 assert (pbBuffer != NULL && "CLuaScript::CompileBuffer -> pbBuffer == NULL");
176 assert (szLen != 0 && "CLuaScript::CompileBuffer -> szLen == 0");
177 assert (m_vm.Ok () && "VM Not OK");
178
179 // Make sure we have the correct "this" table
180 CLuaThis luaThis (m_vm, m_iThisRef);
181
182 return m_vm.RunBuffer (pbBuffer, szLen);
183 }
184
185 //============================================================================
186 // bool CLuaScript::CompileBuffer
187 //---------------------------------------------------------------------------
188 // Compiles a given file
189 //
190 // Parameter Dir Description
191 // --------- --- -----------
192 // strFilename IN File name to compile
193 //
194 // Return
195 // ------
196 // Success
197 //
198 //============================================================================
199 bool CLuaScript::CompileFile (const char *strFilename)
200 {
201 assert (strFilename != NULL && "CLuaScript::CompileFile -> strFilename == NULL");
202 assert (m_vm.Ok () && "VM Not OK");
203
204 // Make sure we have the correct "this" table
205 CLuaThis luaThis (m_vm, m_iThisRef);
206
207 return m_vm.RunFile (strFilename);
208 }
209
210 //============================================================================
211 // int CLuaScript::RegisterFunction
212 //---------------------------------------------------------------------------
213 // Registers a function with Lua
214 //
215 // Parameter Dir Description
216 // --------- --- -----------
217 // strFuncName IN Function name
218 //
219 // Return
220 // ------
221 // Success
222 //
223 //============================================================================
224 int CLuaScript::RegisterFunction (const char *strFuncName)
225 {
226 assert (strFuncName != NULL && "CLuaScript::RegisterFunction -> strFuncName == NULL");
227 assert (m_vm.Ok () && "VM Not OK");
228
229 int iMethodIdx = -1;
230
231 CLuaRestoreStack rs (m_vm);
232
233 BEGIN_LUA_CHECK (m_vm)
234 iMethodIdx = ++m_nMethods;
235
236 // Register a function with the lua script. Added it to the "this" table
237 lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef);
238
239 // Push the function and parameters
240 lua_pushstring (state, strFuncName);
241 lua_pushnumber (state, (lua_Number) iMethodIdx);
242 lua_pushcclosure (state, LuaCallback, 1);
243 lua_settable (state, -3);
244
245 END_LUA_CHECK
246
247 return iMethodIdx;
248 }
249
250 //============================================================================
251 // bool CLuaScript::SelectScriptFunction
252 //---------------------------------------------------------------------------
253 // Selects a script function to run
254 //
255 // Parameter Dir Description
256 // --------- --- -----------
257 // strFuncName IN Function name
258 //
259 // Return
260 // ------
261 // Success
262 //
263 //============================================================================
264 bool CLuaScript::SelectScriptFunction (const char *strFuncName)
265 {
266 assert (strFuncName != NULL && "CLuaScript::SelectScriptFunction -> strFuncName == NULL");
267 assert (m_vm.Ok () && "VM Not OK");
268
269 bool fSuccess = true;
270
271 BEGIN_LUA_CHECK (m_vm)
272 // Look up function name
273 lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef);
274 lua_pushstring (state, strFuncName);
275 lua_rawget (state, -2);
276 lua_remove (state, -2);
277
278 // Put the "this" table back
279 lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef);
280
281 // Check that we have a valid function
282 if (!lua_isfunction (state, -2))
283 {
284 fSuccess = false;
285 lua_pop (state, 2);
286 }
287 else
288 {
289 m_nArgs = 0;
290 m_strFunctionName = strFuncName;
291 }
292 END_LUA_CHECK
293
294 return fSuccess;
295 }
296
297 //============================================================================
298 // bool CLuaScript::ScriptHasFunction
299 //---------------------------------------------------------------------------
300 // Checks to see if a function exists
301 //
302 // Parameter Dir Description
303 // --------- --- -----------
304 // strScriptName IN Function name
305 //
306 // Return
307 // ------
308 // Success
309 //
310 //============================================================================
311 bool CLuaScript::ScriptHasFunction (const char *strScriptName)
312 {
313 assert (strScriptName != NULL && "CLuaScript::ScriptHasFunction -> strScriptName == NULL");
314 assert (m_vm.Ok () && "VM Not OK");
315
316 CLuaRestoreStack rs (m_vm);
317
318 bool fFoundFunc = false;
319
320 BEGIN_LUA_CHECK (m_vm)
321 lua_rawgeti (state, LUA_REGISTRYINDEX, m_iThisRef);
322 lua_pushstring (state, strScriptName);
323 lua_rawget (state, -2);
324 lua_remove (state, -2);
325
326 if (lua_isfunction (state, -1))
327 {
328 fFoundFunc = true;
329 }
330 END_LUA_CHECK
331
332 return fFoundFunc;
333 }
334
335 //============================================================================
336 // void CLuaScript::AddParam
337 //---------------------------------------------------------------------------
338 // Adds a parameter to the parameter list
339 //
340 // Parameter Dir Description
341 // --------- --- -----------
342 // string IN string param
343 //
344 // Return
345 // ------
346 // None.
347 //
348 //============================================================================
349 void CLuaScript::AddParam (char *string)
350 {
351 assert (string != NULL && "CLuaScript::AddParam -> string == NULL");
352 assert (m_vm.Ok () && "VM Not OK");
353
354 BEGIN_LUA_CHECK (m_vm)
355 lua_pushstring (state, string);
356 ++m_nArgs;
357 END_LUA_CHECK
358 }
359
360 //============================================================================
361 // void CLuaScript::AddParam
362 //---------------------------------------------------------------------------
363 // Adds a parameter to the parameter list
364 //
365 // Parameter Dir Description
366 // --------- --- -----------
367 // iInt IN int param
368 //
369 // Return
370 // ------
371 // None.
372 //
373 //============================================================================
374 void CLuaScript::AddParam (int iInt)
375 {
376 assert (m_vm.Ok () && "VM Not OK");
377
378 BEGIN_LUA_CHECK (m_vm)
379 lua_pushnumber (state, (lua_Number) iInt);
380 ++m_nArgs;
381 END_LUA_CHECK
382 }
383
384 //============================================================================
385 // void CLuaScript::AddParam
386 //---------------------------------------------------------------------------
387 // Adds a parameter to the parameter list
388 //
389 // Parameter Dir Description
390 // --------- --- -----------
391 // fFloat IN float param
392 //
393 // Return
394 // ------
395 // None.
396 //
397 //============================================================================
398 void CLuaScript::AddParam (float fFloat)
399 {
400 assert (m_vm.Ok () && "VM Not OK");
401
402 BEGIN_LUA_CHECK (m_vm)
403 lua_pushnumber (state, (lua_Number) fFloat);
404 ++m_nArgs;
405 END_LUA_CHECK
406 }
407
408 //============================================================================
409 // bool CLuaScript::Go
410 //---------------------------------------------------------------------------
411 // Runs the selected script function
412 //
413 // Parameter Dir Description
414 // --------- --- -----------
415 // nReturns IN Number of expected returns
416 //
417 // Return
418 // ------
419 // None.
420 //
421 //============================================================================
422 bool CLuaScript::Go (int nReturns /* = 0 */)
423 {
424 assert (m_vm.Ok () && "VM Not OK");
425
426 // At this point there should be a parameters and a function on the
427 // Lua stack. Each function get a "this" parameter as default and is
428 // pushed onto the stack when the method is selected
429
430 bool fSuccess = m_vm.CallFunction (m_nArgs + 1, nReturns);
431
432 if (fSuccess == true && nReturns > 0)
433 {
434 // Check for returns
435 HandleReturns (m_vm, m_strFunctionName);
436 lua_pop ((lua_State *) m_vm, nReturns);
437 }
438
439 return fSuccess;
440 }