source: Plugins/luaScripting/Script.cpp @ 19

Revision 19, 7.2 KB checked in by art, 12 years ago (diff)
Line 
1/***************************************************************************
2 *                                                                         *
3 *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
4 *       mailto: <tevs@mpi-sb.mpg.de>                                      *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 ***************************************************************************/
12
13#include "Script.h"
14#include <boost/lexical_cast.hpp>
15
16lua_State*      LuaScript::State = NULL;
17
18#if 1
19// Dump all the contents of your lua_state (Lua Stack)
20 // Find out the location of ur table and try to print out the details by
21 // modifying the below code
22 
23 static void stackDump (lua_State *L) { 
24         int i;
25         int top = lua_gettop(L);
26         printf("Stack has %d elements\n", top);
27         for (i = 1; i <= top; i++) { /* repeat for each level */
28                 int t = lua_type(L, i);
29                 switch (t) {
30 
31                         case LUA_TSTRING: /* strings */
32                                 printf("string: `%s'", lua_tostring(L, i));
33                                 break;
34 
35                        case LUA_TBOOLEAN: /* booleans */
36                                 printf(lua_toboolean(L, i) ? "true" : "false");
37                                 break;
38 
39                        case LUA_TNUMBER: /* numbers */
40                                printf("number: %g", lua_tonumber(L, i));
41                                 break;
42 
43                        default: /* other values */
44                                 printf("type: %s", lua_typename(L, t));
45                                 break; 
46                 }
47                 printf("\n"); /* put a separator */
48         }
49         printf("\n"); /* end the listing */
50 }
51#endif
52
53//----------------------------------------------------------------------------------
54LuaScript::LuaScript() : IScript("LuaScript")
55{
56        mFuncRef = LUA_NOREF;
57}
58
59//----------------------------------------------------------------------------------
60LuaScript::~LuaScript()
61{
62
63}
64
65
66//----------------------------------------------------------------------------------
67Result LuaScript::loadFromString(const std::string& str)
68{
69        static bool loaded = false;
70       
71        // load lua from string
72        mContent = str;
73
74        // first check if there is a lua function calling loadScript
75        // which is able to load scripts and setup environments
76        lua_getglobal(State, "loadstringscript");
77        if (lua_isfunction(State, -1))
78        {
79                // ok the function is defined, so use it to load scripts
80                lua_pushstring(State, str.c_str());
81                if (lua_pcall(State, 1, 1, 0))
82                {
83                        const char* error = lua_tostring(State, -1);
84                        lua_pop(State, lua_gettop(State));
85                        pushErrorMessage(std::string("luaScript: Error in execution in loadstringscript - ") + std::string(error));
86                        return SCRIPT_ERROR;
87                }
88                loaded = true;
89               
90        // the function is not defined, so load the stuff in the default way
91        }else{
92                // use the default function instead
93                int32 result = luaL_dostring(State, mContent.c_str());
94                if (result == LUA_ERRSYNTAX){
95                        NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "luaScript: Error in script %s", getResName().c_str());
96                        return SCRIPT_PARSE_ERROR;
97                }else if (result == LUA_ERRMEM){
98                        NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "luaScript: Not enough memory to load script %s", getResName().c_str());
99                        return OUT_OF_MEMORY;
100                }
101        }
102       
103        // now let keep the script in memory
104        mFuncRef = luaL_ref(State, LUA_REGISTRYINDEX);
105        if (mFuncRef == LUA_REFNIL && loaded){
106                NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "luaScript: Script could not be compiled %s", getResName().c_str());
107                return SCRIPT_ERROR;
108        }
109
110        return OK;
111}
112               
113//----------------------------------------------------------------------------------
114Result LuaScript::unloadRes()
115{
116        if (isResLoaded())
117        {
118                luaL_unref(State, LUA_REGISTRYINDEX, mFuncRef);
119                mFuncRef = LUA_NOREF;
120        }
121       
122        return OK;
123}
124
125
126//----------------------------------------------------------------------------------
127Result LuaScript::run()
128{
129        // check consistency
130        if (lua_gettop(State))
131        {
132                pushErrorMessage(std::string("luaScript: The stack must be empty when calling a function!"));
133                stackDump(State);
134                return SCRIPT_ERROR;
135        }
136       
137        // load the script on the top
138        lua_rawgeti(State, LUA_REGISTRYINDEX, mFuncRef);
139        lua_getfield(State, -1, "main");
140
141        if (lua_isfunction(State, -1))
142        {
143                // let lua run the script and check for return codes
144                int32 res = lua_pcall(State, 0, LUA_MULTRET, 0);
145       
146                if (res != 0){
147                        // get error from the lua stack and give it in the log file
148                        const char* error = lua_tostring(State, -1);
149                        lua_pop(State, lua_gettop(State));
150                        pushErrorMessage(std::string("luaScript: Error in execution - ") + std::string(error));
151                        return SCRIPT_ERROR;
152                }       
153        }
154       
155        // we just run the script, we are not interested in results, so clear the stack
156        lua_pop(State, lua_gettop(State));
157
158        return OK;
159}
160
161
162//----------------------------------------------------------------------------------
163Result LuaScript::callfunc(const std::string& funcName, ScriptResult& result)
164{
165        // check consistency
166        if (lua_gettop(State))
167        {
168                pushErrorMessage(std::string("luaScript: The stack must be empty when calling a function!"));
169                stackDump(State);
170                return SCRIPT_ERROR;
171        }
172
173        // load the script on the top
174        lua_rawgeti(State, LUA_REGISTRYINDEX, mFuncRef);
175
176        // set the function to be called
177        lua_getfield(State, -1, funcName.c_str());
178
179        // check if is a valid function
180        if (lua_gettop(State) == 0 || lua_isfunction(State, -1) == 0){
181                lua_pop(State, lua_gettop(State));
182                pushErrorMessage(std::string("luaScript: Can not find function ") + funcName);
183                return SCRIPT_FUNCTION_NOT_FOUND;
184        }
185
186        // parameter count
187        int32 argn = 0;
188       
189        // ok retrieve arguments from the argument list and push them on lua stack
190        while (true)
191        {
192                // get the arguemnt
193                std::string type, value;
194                int32 count = popArgument(funcName, type, value);
195                if (count == -1) break;
196
197                // now check for the type and do conversion
198                try{
199                        if (type == "string")
200                                lua_pushstring(State, value.c_str());
201                        else if (type == "number")
202                                lua_pushnumber(State, boost::lexical_cast<lua_Number>(value));
203                        else if (type == "bool"){
204                                if (value == "yes" || value == "true" || value == "on" || value == "1")
205                                        lua_pushboolean(State, 1);
206                                else
207                                        lua_pushboolean(State, 0);
208                        }
209                } catch (boost::bad_lexical_cast s) {
210                        pushErrorMessage(std::string("luaScript: Wrong parameter value ") + value + std::string(" of type ") + type);
211                        return SCRIPT_WRONG_PARAMETER_VALUE;
212                }
213               
214                // increase argument number
215                argn ++;
216        }
217
218        // call the function and check for return code
219        int32 res = lua_pcall(State, argn, LUA_MULTRET, 0);
220
221        if (res != 0){
222                // get error from the lua stack and give it in the log file
223                const char* error = lua_tostring(State, -1);
224                lua_pop(State, lua_gettop(State));
225                pushErrorMessage(std::string("luaScript: Error in execution - ") + std::string(error));
226                return SCRIPT_ERROR;
227        }
228
229        // now retrieve all results from the stack and return
230        // do only get results until the last element on the stack
231        // because this is our environment tabkle
232        result.empty();
233        while (lua_gettop(State) > 1){
234                const char* str = lua_popstring(State);
235                result , std::string(str);
236        }
237
238        // remove the last element from the stack
239        lua_pop(State, 1);
240       
241        return OK;
242}
Note: See TracBrowser for help on using the repository browser.