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