$search
00001 00002 /*************************************************************************** 00003 * context.cpp - Fawkes Lua Context 00004 * 00005 * Created: Fri May 23 15:53:54 2008 00006 * Copyright 2006-2010 Tim Niemueller [www.niemueller.de] 00007 * 2010 Carnegie Mellon University 00008 * 2010 Intel Labs Pittsburgh 00009 ****************************************************************************/ 00010 00011 /* This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL file in the doc directory. 00022 */ 00023 00024 #ifdef USE_ROS 00025 # include <lua_utils/context.h> 00026 # include <lua_utils/context_watcher.h> 00027 #else 00028 # include <lua/context.h> 00029 # include <lua/context_watcher.h> 00030 # include <core/threading/mutex.h> 00031 # include <core/threading/mutex_locker.h> 00032 # include <core/exceptions/system.h> 00033 # include <core/exceptions/software.h> 00034 # include <utils/logging/liblogger.h> 00035 #endif 00036 00037 #include <algorithm> 00038 #include <tolua++.h> 00039 #include <cstdlib> 00040 #include <cstring> 00041 #include <unistd.h> 00042 00043 namespace fawkes { 00044 #if 0 /* just to make Emacs auto-indent happy */ 00045 } 00046 #endif 00047 00074 LuaContext::LuaContext(bool watch_dirs, bool enable_tracebacks) 00075 { 00076 __owns_L = true; 00077 __enable_tracebacks = enable_tracebacks; 00078 00079 if ( watch_dirs ) { 00080 __fam = new FileAlterationMonitor(); 00081 __fam->add_filter("^[^.].*\\.lua$"); 00082 __fam->add_listener(this); 00083 } else { 00084 __fam = NULL; 00085 } 00086 #ifndef USE_ROS 00087 __lua_mutex = new Mutex(); 00088 #endif 00089 00090 __start_script = NULL; 00091 __L = init_state(); 00092 } 00093 00094 00103 LuaContext::LuaContext(lua_State *L) 00104 { 00105 __owns_L = false; 00106 __L = L; 00107 #ifndef USE_ROS 00108 __lua_mutex = new Mutex(); 00109 #endif 00110 __start_script = NULL; 00111 __fam = NULL; 00112 } 00113 00115 LuaContext::~LuaContext() 00116 { 00117 #ifndef USE_ROS 00118 __lua_mutex->lock(); 00119 delete __lua_mutex; 00120 #endif 00121 delete __fam; 00122 if ( __start_script ) free(__start_script); 00123 if ( __owns_L) { 00124 #ifndef USE_ROS 00125 MutexLocker(__watchers.mutex()); 00126 LockList<LuaContextWatcher *>::iterator i; 00127 #else 00128 std::list<LuaContextWatcher *>::iterator i; 00129 #endif 00130 for (i = __watchers.begin(); i != __watchers.end(); ++i) { 00131 try { 00132 (*i)->lua_finalize(this); 00133 } catch (Exception &e) { 00134 #ifndef USE_ROS 00135 LibLogger::log_warn("LuaContext", "Context watcher threw an exception on finalize, " 00136 "exception follows"); 00137 LibLogger::log_warn("LuaContext", e); 00138 #endif 00139 } 00140 } 00141 00142 lua_close(__L); 00143 } 00144 #ifndef USE_ROS 00145 delete __lua_mutex; 00146 #endif 00147 } 00148 00149 00154 lua_State * 00155 LuaContext::init_state() 00156 { 00157 lua_State *L = luaL_newstate(); 00158 luaL_openlibs(L); 00159 00160 if (__enable_tracebacks) { 00161 lua_getglobal(L, "debug"); 00162 lua_getfield(L, -1, "traceback"); 00163 lua_remove(L, -2); 00164 } 00165 00166 // Add package paths 00167 for (__slit = __package_dirs.begin(); __slit != __package_dirs.end(); ++__slit) { 00168 do_string(L, "package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", __slit->c_str(), __slit->c_str()); 00169 } 00170 00171 for (__slit = __cpackage_dirs.begin(); __slit != __cpackage_dirs.end(); ++__slit) { 00172 do_string(L, "package.cpath = package.cpath .. \";%s/?.so\"", __slit->c_str()); 00173 } 00174 00175 // load base packages 00176 for (__slit = __packages.begin(); __slit != __packages.end(); ++__slit) { 00177 do_string(L, "require(\"%s\")", __slit->c_str()); 00178 } 00179 00180 for ( __utit = __usertypes.begin(); __utit != __usertypes.end(); ++__utit) { 00181 tolua_pushusertype(L, __utit->second.first, __utit->second.second.c_str()); 00182 lua_setglobal(L, __utit->first.c_str()); 00183 } 00184 00185 for ( __strings_it = __strings.begin(); __strings_it != __strings.end(); ++__strings_it) { 00186 lua_pushstring(L, __strings_it->second.c_str()); 00187 lua_setglobal(L, __strings_it->first.c_str()); 00188 } 00189 00190 for ( __booleans_it = __booleans.begin(); __booleans_it != __booleans.end(); ++__booleans_it) { 00191 lua_pushboolean(L, __booleans_it->second); 00192 lua_setglobal(L, __booleans_it->first.c_str()); 00193 } 00194 00195 for ( __numbers_it = __numbers.begin(); __numbers_it != __numbers.end(); ++__numbers_it) { 00196 lua_pushnumber(L, __numbers_it->second); 00197 lua_setglobal(L, __numbers_it->first.c_str()); 00198 } 00199 00200 for ( __integers_it = __integers.begin(); __integers_it != __integers.end(); ++__integers_it) { 00201 lua_pushinteger(L, __integers_it->second); 00202 lua_setglobal(L, __integers_it->first.c_str()); 00203 } 00204 00205 for ( __cfunctions_it = __cfunctions.begin(); __cfunctions_it != __cfunctions.end(); ++__cfunctions_it) { 00206 lua_pushcfunction(L, __cfunctions_it->second); 00207 lua_setglobal(L, __cfunctions_it->first.c_str()); 00208 } 00209 00210 LuaContext *tmpctx = new LuaContext(L); 00211 #ifndef USE_ROS 00212 MutexLocker(__watchers.mutex()); 00213 LockList<LuaContextWatcher *>::iterator i; 00214 #else 00215 std::list<LuaContextWatcher *>::iterator i; 00216 #endif 00217 for (i = __watchers.begin(); i != __watchers.end(); ++i) { 00218 try { 00219 (*i)->lua_init(tmpctx); 00220 } catch (...) { 00221 delete tmpctx; 00222 lua_close(L); 00223 throw; 00224 } 00225 } 00226 delete tmpctx; 00227 00228 if ( __start_script ) { 00229 if (access(__start_script, R_OK) == 0) { 00230 // it's a file and we can access it, execute it! 00231 do_file(L, __start_script); 00232 } else { 00233 do_string(L, "require(\"%s\")", __start_script); 00234 } 00235 } 00236 00237 return L; 00238 } 00239 00240 00252 void 00253 LuaContext::set_start_script(const char *start_script) 00254 { 00255 if ( __start_script ) free(__start_script); 00256 if ( start_script ) { 00257 __start_script = strdup(start_script); 00258 if (access(__start_script, R_OK) == 0) { 00259 // it's a file and we can access it, execute it! 00260 do_file(__start_script); 00261 } else { 00262 do_string("require(\"%s\")", __start_script); 00263 } 00264 } else { 00265 __start_script = NULL; 00266 } 00267 } 00268 00269 00274 void 00275 LuaContext::restart() 00276 { 00277 #ifndef USE_ROS 00278 MutexLocker lock(__lua_mutex); 00279 #endif 00280 try { 00281 lua_State *L = init_state(); 00282 lua_State *tL = __L; 00283 00284 #ifndef USE_ROS 00285 MutexLocker(__watchers.mutex()); 00286 LockList<LuaContextWatcher *>::iterator i; 00287 #else 00288 std::list<LuaContextWatcher *>::iterator i; 00289 #endif 00290 for (i = __watchers.begin(); i != __watchers.end(); ++i) { 00291 try { 00292 (*i)->lua_finalize(this); 00293 } catch (Exception &e) { 00294 #ifndef USE_ROS 00295 LibLogger::log_warn("LuaContext", "Context watcher threw an exception on finalize, " 00296 "exception follows"); 00297 LibLogger::log_warn("LuaContext", e); 00298 #endif 00299 } 00300 } 00301 00302 // swap and destroy old context 00303 __L = L; 00304 lua_close(tL); 00305 00306 for (i = __watchers.begin(); i != __watchers.end(); ++i) { 00307 try { 00308 (*i)->lua_restarted(this); 00309 } catch (Exception &e) { 00310 #ifndef USE_ROS 00311 LibLogger::log_warn("LuaContext", "Context watcher threw an exception on restart, " 00312 "exception follows"); 00313 LibLogger::log_warn("LuaContext", e); 00314 #endif 00315 } 00316 } 00317 00318 } catch (Exception &e) { 00319 #ifndef USE_ROS 00320 LibLogger::log_error("LuaContext", "Could not restart Lua instance, an error " 00321 "occured while initializing new state. Keeping old state."); 00322 LibLogger::log_error("LuaContext", e); 00323 #endif 00324 } 00325 } 00326 00327 00333 void 00334 LuaContext::add_package_dir(const char *path) 00335 { 00336 #ifndef USE_ROS 00337 MutexLocker lock(__lua_mutex); 00338 #endif 00339 00340 do_string(__L, "package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", path, path); 00341 00342 __package_dirs.push_back(path); 00343 if ( __fam ) __fam->watch_dir(path); 00344 } 00345 00346 00352 void 00353 LuaContext::add_cpackage_dir(const char *path) 00354 { 00355 #ifndef USE_ROS 00356 MutexLocker lock(__lua_mutex); 00357 #endif 00358 00359 do_string(__L, "package.cpath = package.cpath .. \";%s/?.so\"", path); 00360 00361 __cpackage_dirs.push_back(path); 00362 if ( __fam ) __fam->watch_dir(path); 00363 } 00364 00365 00371 void 00372 LuaContext::add_package(const char *package) 00373 { 00374 #ifndef USE_ROS 00375 MutexLocker lock(__lua_mutex); 00376 #endif 00377 00378 if (find(__packages.begin(), __packages.end(), package) == __packages.end()) { 00379 do_string(__L, "require(\"%s\")", package); 00380 00381 __packages.push_back(package); 00382 } 00383 } 00384 00389 void 00390 LuaContext::add_watchdir(const char *path) 00391 { 00392 #ifndef USE_ROS 00393 MutexLocker lock(__lua_mutex); 00394 #endif 00395 if ( __fam ) __fam->watch_dir(path); 00396 } 00397 00401 void 00402 LuaContext::add_watchfile(const char *path) 00403 { 00404 #ifndef USE_ROS 00405 MutexLocker lock(__lua_mutex); 00406 #endif 00407 if ( __fam ) __fam->watch_file(path); 00408 } 00409 00410 00416 lua_State * 00417 LuaContext::get_lua_state() 00418 { 00419 return __L; 00420 } 00421 00422 00423 #ifndef USE_ROS 00424 00425 void 00426 LuaContext::lock() 00427 { 00428 __lua_mutex->lock(); 00429 } 00430 00431 00435 bool 00436 LuaContext::try_lock() 00437 { 00438 return __lua_mutex->try_lock(); 00439 } 00440 00441 00443 void 00444 LuaContext::unlock() 00445 { 00446 __lua_mutex->unlock(); 00447 } 00448 #endif 00449 00453 void 00454 LuaContext::do_file(const char *filename) 00455 { 00456 #ifndef USE_ROS 00457 MutexLocker lock(__lua_mutex); 00458 #endif 00459 do_file(__L, filename); 00460 } 00461 00462 00467 void 00468 LuaContext::do_file(lua_State *L, const char *filename) 00469 { 00470 // Load initialization code 00471 int err = 0; 00472 std::string errmsg; 00473 if ( (err = luaL_loadfile(L, filename)) != 0) { 00474 errmsg = lua_tostring(L, -1); 00475 lua_pop(L, 1); 00476 switch (err) { 00477 case LUA_ERRSYNTAX: 00478 #ifndef USE_ROS 00479 throw SyntaxErrorException("Lua syntax error in file %s: %s", filename, errmsg.c_str()); 00480 #else 00481 throw Exception(std::string("Lua syntax error in file ") + filename + ": " + errmsg); 00482 #endif 00483 00484 case LUA_ERRMEM: 00485 #ifndef USE_ROS 00486 throw OutOfMemoryException("Could not load Lua file %s", filename); 00487 #else 00488 throw Exception(std::string("Out of Memory. Could not load Lua file ") + filename); 00489 #endif 00490 00491 case LUA_ERRFILE: 00492 #ifndef USE_ROS 00493 throw CouldNotOpenFileException(filename, errmsg.c_str()); 00494 #else 00495 throw Exception(std::string("Could not open file file ") + filename + ": " + errmsg); 00496 #endif 00497 } 00498 } 00499 00500 int errfunc = __enable_tracebacks ? 1 : 0; 00501 if ( (err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0 ) { 00502 // There was an error while executing the initialization file 00503 errmsg = lua_tostring(L, -1); 00504 lua_pop(L, 1); 00505 switch (err) { 00506 case LUA_ERRRUN: 00507 throw LuaRuntimeException("do_file", errmsg.c_str()); 00508 00509 case LUA_ERRMEM: 00510 #ifndef USE_ROS 00511 throw OutOfMemoryException("Could not execute Lua file %s", filename); 00512 #else 00513 throw Exception(std::string("Out of Memory. Could not execute Lua file ") + filename); 00514 #endif 00515 00516 case LUA_ERRERR: 00517 throw LuaErrorException("do_file", errmsg.c_str()); 00518 00519 default: 00520 throw LuaErrorException("do_file/unknown error", errmsg.c_str()); 00521 } 00522 } 00523 00524 } 00525 00526 00532 void 00533 LuaContext::do_string(lua_State *L, const char *format, ...) 00534 { 00535 va_list arg; 00536 va_start(arg, format); 00537 char *s; 00538 if (vasprintf(&s, format, arg) == -1) { 00539 throw Exception("LuaContext::do_string: Could not form string"); 00540 } 00541 00542 int rv = 0; 00543 int errfunc = __enable_tracebacks ? 1 : 0; 00544 rv = (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, errfunc)); 00545 00546 free(s); 00547 va_end(arg); 00548 00549 if (rv != 0) { 00550 std::string errmsg = lua_tostring(L, -1); 00551 lua_pop(L, 1); 00552 throw LuaRuntimeException("do_string", errmsg.c_str()); 00553 } 00554 } 00555 00556 00561 void 00562 LuaContext::do_string(const char *format, ...) 00563 { 00564 #ifndef USE_ROS 00565 MutexLocker lock(__lua_mutex); 00566 #endif 00567 va_list arg; 00568 va_start(arg, format); 00569 char *s; 00570 if (vasprintf(&s, format, arg) == -1) { 00571 throw Exception("LuaContext::do_string: Could not form string"); 00572 } 00573 00574 int rv = 0; 00575 int errfunc = __enable_tracebacks ? 1 : 0; 00576 rv = (luaL_loadstring(__L, s) || lua_pcall(__L, 0, LUA_MULTRET, errfunc)); 00577 00578 free(s); 00579 va_end(arg); 00580 00581 if ( rv != 0 ) { 00582 std::string errmsg = lua_tostring(__L, -1); 00583 lua_pop(__L, 1); 00584 throw LuaRuntimeException("do_string", errmsg.c_str()); 00585 } 00586 } 00587 00588 00593 void 00594 LuaContext::load_string(const char *s) 00595 { 00596 int err; 00597 if ( (err = luaL_loadstring(__L, s)) != 0 ) { 00598 std::string errmsg = lua_tostring(__L, -1); 00599 lua_pop(__L, 1); 00600 switch (err) { 00601 case LUA_ERRSYNTAX: 00602 #ifndef USE_ROS 00603 throw SyntaxErrorException("Lua syntax error in string '%s': %s", 00604 s, errmsg.c_str()); 00605 #else 00606 throw Exception(std::string("Lua syntax error in string '") + s + "': " + errmsg); 00607 #endif 00608 00609 case LUA_ERRMEM: 00610 #ifndef USE_ROS 00611 throw OutOfMemoryException("Could not load Lua string '%s'", s); 00612 #else 00613 throw Exception(std::string("Out of Memory. Cannot load string '") + s + "'"); 00614 #endif 00615 } 00616 } 00617 } 00618 00619 00629 void 00630 LuaContext::pcall(int nargs, int nresults, int errfunc) 00631 { 00632 int err = 0; 00633 if ( ! errfunc && __enable_tracebacks ) errfunc = 1; 00634 if ( (err = lua_pcall(__L, nargs, nresults, errfunc)) != 0 ) { 00635 std::string errmsg = lua_tostring(__L, -1); 00636 lua_pop(__L, 1); 00637 switch (err) { 00638 case LUA_ERRRUN: 00639 throw LuaRuntimeException("pcall", errmsg.c_str()); 00640 00641 case LUA_ERRMEM: 00642 #ifndef USE_ROS 00643 throw OutOfMemoryException("Could not execute Lua chunk via pcall"); 00644 #else 00645 throw Exception("Ouf of memory, cannot execute Lua chunk via pcall"); 00646 #endif 00647 00648 case LUA_ERRERR: 00649 throw LuaErrorException("pcall", errmsg.c_str()); 00650 } 00651 } 00652 } 00653 00654 00663 void 00664 LuaContext::assert_unique_name(const char *name, std::string type) 00665 { 00666 if ( (type != "usertype") && (__usertypes.find(name) != __usertypes.end()) ) { 00667 #ifndef USE_ROS 00668 throw Exception("User type entry already exists for name %s", name); 00669 #else 00670 throw Exception(std::string("User type entry already exists for name ") + name); 00671 #endif 00672 } 00673 if ( (type != "string") && (__strings.find(name) != __strings.end()) ) { 00674 #ifndef USE_ROS 00675 throw Exception("String entry already exists for name %s", name); 00676 #else 00677 throw Exception(std::string("String entry already exists for name ") + name); 00678 #endif 00679 } 00680 if ( (type != "boolean") && (__booleans.find(name) != __booleans.end()) ) { 00681 #ifndef USE_ROS 00682 throw Exception("Boolean entry already exists for name %s", name); 00683 #else 00684 throw Exception(std::string("Boolean entry already exists for name ") + name); 00685 #endif 00686 } 00687 if ( (type != "number") && (__numbers.find(name) != __numbers.end()) ) { 00688 #ifndef USE_ROS 00689 throw Exception("Number entry already exists for name %s", name); 00690 #else 00691 throw Exception(std::string("Number entry already exists for name ") + name); 00692 #endif 00693 } 00694 if ( (type != "integer") && (__integers.find(name) != __integers.end()) ) { 00695 #ifndef USE_ROS 00696 throw Exception("Integer entry already exists for name %s", name); 00697 #else 00698 throw Exception(std::string("Integer entry already exists for name ") + name); 00699 #endif 00700 } 00701 if ( (type != "cfunction") && (__cfunctions.find(name) != __cfunctions.end()) ) { 00702 #ifndef USE_ROS 00703 throw Exception("Cfunction entry already exists for name %s", name); 00704 #else 00705 throw Exception(std::string("Cfunction entry already exists for name ") + name); 00706 #endif 00707 } 00708 } 00709 00710 00717 void 00718 LuaContext::set_usertype(const char *name, void *data, 00719 const char *type_name, const char *name_space) 00720 { 00721 #ifndef USE_ROS 00722 MutexLocker lock(__lua_mutex); 00723 #endif 00724 std::string type_n = type_name; 00725 if ( name_space ) { 00726 type_n = std::string(name_space) + "::" + type_name; 00727 } 00728 00729 assert_unique_name(name, "usertype"); 00730 00731 __usertypes[name] = std::make_pair(data, type_n); 00732 00733 tolua_pushusertype(__L, data, type_n.c_str()); 00734 lua_setglobal(__L, name); 00735 } 00736 00737 00742 void 00743 LuaContext::set_string(const char *name, const char *value) 00744 { 00745 #ifndef USE_ROS 00746 MutexLocker lock(__lua_mutex); 00747 #endif 00748 assert_unique_name(name, "string"); 00749 00750 __strings[name] = value; 00751 00752 lua_pushstring(__L, value); 00753 lua_setglobal(__L, name); 00754 } 00755 00756 00761 void 00762 LuaContext::set_boolean(const char *name, bool value) 00763 { 00764 #ifndef USE_ROS 00765 MutexLocker lock(__lua_mutex); 00766 #endif 00767 assert_unique_name(name, "boolean"); 00768 00769 __booleans[name] = value; 00770 00771 lua_pushboolean(__L, value ? 1 : 0); 00772 lua_setglobal(__L, name); 00773 } 00774 00775 00780 void 00781 LuaContext::set_number(const char *name, lua_Number value) 00782 { 00783 #ifndef USE_ROS 00784 MutexLocker lock(__lua_mutex); 00785 #endif 00786 assert_unique_name(name, "number"); 00787 00788 __numbers[name] = value; 00789 00790 lua_pushnumber(__L, value); 00791 lua_setglobal(__L, name); 00792 } 00793 00794 00799 void 00800 LuaContext::set_integer(const char *name, lua_Integer value) 00801 { 00802 #ifndef USE_ROS 00803 MutexLocker lock(__lua_mutex); 00804 #endif 00805 assert_unique_name(name, "integer"); 00806 00807 __integers[name] = value; 00808 00809 lua_pushinteger(__L, value); 00810 lua_setglobal(__L, name); 00811 } 00812 00817 void 00818 LuaContext::set_cfunction(const char *name, lua_CFunction function) 00819 { 00820 #ifndef USE_ROS 00821 MutexLocker lock(__lua_mutex); 00822 #endif 00823 assert_unique_name(name, "cfunction"); 00824 00825 __cfunctions[name] = function; 00826 00827 lua_pushcfunction(__L, function); 00828 lua_setglobal(__L, name); 00829 } 00830 00831 00835 void 00836 LuaContext::push_boolean(bool value) 00837 { 00838 #ifndef USE_ROS 00839 MutexLocker lock(__lua_mutex); 00840 #endif 00841 lua_pushboolean(__L, value ? 1 : 0); 00842 } 00843 00844 00849 void 00850 LuaContext::push_fstring(const char *format, ...) 00851 { 00852 #ifndef USE_ROS 00853 MutexLocker lock(__lua_mutex); 00854 #endif 00855 va_list arg; 00856 va_start(arg, format); 00857 lua_pushvfstring(__L, format, arg); 00858 va_end(arg); 00859 } 00860 00861 00865 void 00866 LuaContext::push_integer(lua_Integer value) 00867 { 00868 #ifndef USE_ROS 00869 MutexLocker lock(__lua_mutex); 00870 #endif 00871 lua_pushinteger(__L, value); 00872 } 00873 00874 00878 void 00879 LuaContext::push_light_user_data(void *p) 00880 { 00881 #ifndef USE_ROS 00882 MutexLocker lock(__lua_mutex); 00883 #endif 00884 lua_pushlightuserdata(__L, p); 00885 } 00886 00887 00892 void 00893 LuaContext::push_lstring(const char *s, size_t len) 00894 { 00895 #ifndef USE_ROS 00896 MutexLocker lock(__lua_mutex); 00897 #endif 00898 lua_pushlstring(__L, s, len); 00899 } 00900 00901 00904 void 00905 LuaContext::push_nil() 00906 { 00907 #ifndef USE_ROS 00908 MutexLocker lock(__lua_mutex); 00909 #endif 00910 lua_pushnil(__L); 00911 } 00912 00913 00917 void 00918 LuaContext::push_number(lua_Number value) 00919 { 00920 #ifndef USE_ROS 00921 MutexLocker lock(__lua_mutex); 00922 #endif 00923 lua_pushnumber(__L, value); 00924 } 00925 00926 00930 void 00931 LuaContext::push_string(const char *value) 00932 { 00933 #ifndef USE_ROS 00934 MutexLocker lock(__lua_mutex); 00935 #endif 00936 lua_pushstring(__L, value); 00937 } 00938 00939 00942 void 00943 LuaContext::push_thread() 00944 { 00945 #ifndef USE_ROS 00946 MutexLocker lock(__lua_mutex); 00947 #endif 00948 lua_pushthread(__L); 00949 } 00950 00951 00955 void 00956 LuaContext::push_value(int idx) 00957 { 00958 #ifndef USE_ROS 00959 MutexLocker lock(__lua_mutex); 00960 #endif 00961 lua_pushvalue(__L, idx); 00962 } 00963 00964 00970 void 00971 LuaContext::push_vfstring(const char *format, va_list arg) 00972 { 00973 #ifndef USE_ROS 00974 MutexLocker lock(__lua_mutex); 00975 #endif 00976 lua_pushvfstring(__L, format, arg); 00977 } 00978 00979 00985 void 00986 LuaContext::push_usertype(void *data, const char *type_name, 00987 const char *name_space) 00988 { 00989 #ifndef USE_ROS 00990 MutexLocker lock(__lua_mutex); 00991 #endif 00992 00993 std::string type_n = type_name; 00994 if ( name_space ) { 00995 type_n = std::string(name_space) + "::" + type_name; 00996 } 00997 00998 tolua_pushusertype(__L, data, type_n.c_str()); 00999 } 01000 01004 void 01005 LuaContext::push_cfunction(lua_CFunction function) 01006 { 01007 #ifndef USE_ROS 01008 MutexLocker lock(__lua_mutex); 01009 #endif 01010 lua_pushcfunction(__L, function); 01011 } 01012 01013 01017 void 01018 LuaContext::pop(int n) 01019 { 01020 #ifndef USE_ROS 01021 MutexLocker lock(__lua_mutex); 01022 #endif 01023 if (__enable_tracebacks && (n >= stack_size())) { 01024 throw LuaRuntimeException("pop", "Cannot pop traceback function, invalid n"); 01025 } 01026 lua_pop(__L, n); 01027 } 01028 01032 void 01033 LuaContext::remove(int idx) 01034 { 01035 #ifndef USE_ROS 01036 MutexLocker lock(__lua_mutex); 01037 #endif 01038 if (__enable_tracebacks && ((idx == 1) || (idx == -stack_size()))) { 01039 throw LuaRuntimeException("pop", "Cannot remove traceback function"); 01040 } 01041 lua_remove(__L, idx); 01042 } 01043 01044 01048 int 01049 LuaContext::stack_size() 01050 { 01051 return lua_gettop(__L); 01052 } 01053 01054 01059 void 01060 LuaContext::create_table(int narr, int nrec) 01061 { 01062 lua_createtable(__L, narr, nrec); 01063 } 01064 01065 01072 void 01073 LuaContext::set_table(int t_index) 01074 { 01075 lua_settable(__L, t_index); 01076 } 01077 01078 01087 void 01088 LuaContext::set_field(const char *key, int t_index) 01089 { 01090 lua_setfield(__L, t_index, key); 01091 } 01092 01093 01099 void 01100 LuaContext::set_global(const char *name) 01101 { 01102 lua_setglobal(__L, name); 01103 } 01104 01105 01113 void 01114 LuaContext::get_table(int idx) 01115 { 01116 lua_gettable(__L, idx); 01117 } 01118 01119 01126 void 01127 LuaContext::get_field(int idx, const char *k) 01128 { 01129 lua_getfield(__L, idx, k); 01130 } 01131 01132 01137 void 01138 LuaContext::raw_set(int idx) 01139 { 01140 lua_rawset(__L, idx); 01141 } 01142 01143 01150 void 01151 LuaContext::raw_seti(int idx, int n) 01152 { 01153 lua_rawseti(__L, idx, n); 01154 } 01155 01156 01161 void 01162 LuaContext::raw_get(int idx) 01163 { 01164 lua_rawget(__L, idx); 01165 } 01166 01167 01173 void 01174 LuaContext::raw_geti(int idx, int n) 01175 { 01176 lua_rawgeti(__L, idx, n); 01177 } 01178 01179 01183 void 01184 LuaContext::get_global(const char *name) 01185 { 01186 lua_getglobal(__L, name); 01187 } 01188 01189 01195 void 01196 LuaContext::remove_global(const char *name) 01197 { 01198 #ifndef USE_ROS 01199 MutexLocker lock(__lua_mutex); 01200 #endif 01201 01202 __usertypes.erase(name); 01203 __strings.erase(name); 01204 __booleans.erase(name); 01205 __numbers.erase(name); 01206 __integers.erase(name); 01207 __cfunctions.erase(name); 01208 01209 lua_pushnil(__L); 01210 lua_setglobal(__L, name); 01211 } 01212 01213 01218 lua_Number 01219 LuaContext::to_number(int idx) 01220 { 01221 return lua_tonumber(__L, idx); 01222 } 01223 01224 01229 lua_Integer 01230 LuaContext::to_integer(int idx) 01231 { 01232 return lua_tointeger(__L, idx); 01233 } 01234 01235 01240 bool 01241 LuaContext::to_boolean(int idx) 01242 { 01243 return lua_toboolean(__L, idx); 01244 } 01245 01246 01251 const char * 01252 LuaContext::to_string(int idx) 01253 { 01254 return lua_tostring(__L, idx); 01255 } 01256 01257 01262 bool 01263 LuaContext::is_boolean(int idx) 01264 { 01265 return lua_isboolean(__L, idx); 01266 } 01267 01268 01273 bool 01274 LuaContext::is_cfunction(int idx) 01275 { 01276 return lua_iscfunction(__L, idx); 01277 } 01278 01279 01284 bool 01285 LuaContext::is_function(int idx) 01286 { 01287 return lua_isfunction(__L, idx); 01288 } 01289 01290 01295 bool 01296 LuaContext::is_light_user_data(int idx) 01297 { 01298 return lua_islightuserdata(__L, idx); 01299 } 01300 01301 01306 bool 01307 LuaContext::is_nil(int idx) 01308 { 01309 return lua_isnil(__L, idx); 01310 } 01311 01312 01317 bool 01318 LuaContext::is_number(int idx) 01319 { 01320 return lua_isnumber(__L, idx); 01321 } 01322 01323 01328 bool 01329 LuaContext::is_string(int idx) 01330 { 01331 return lua_isstring(__L, idx); 01332 } 01333 01334 01339 bool 01340 LuaContext::is_table(int idx) 01341 { 01342 return lua_istable(__L, idx); 01343 } 01344 01345 01350 bool 01351 LuaContext::is_thread(int idx) 01352 { 01353 return lua_isthread(__L, idx); 01354 } 01355 01356 01361 size_t 01362 LuaContext::objlen(int idx) 01363 { 01364 return lua_objlen(__L, idx); 01365 } 01366 01367 01373 void 01374 LuaContext::setfenv(int idx) 01375 { 01376 lua_setfenv(__L, idx); 01377 } 01378 01379 01383 void 01384 LuaContext::add_watcher(fawkes::LuaContextWatcher *watcher) 01385 { 01386 #ifndef USE_ROS 01387 __watchers.push_back_locked(watcher); 01388 #else 01389 __watchers.push_back(watcher); 01390 #endif 01391 } 01392 01393 01397 void 01398 LuaContext::remove_watcher(fawkes::LuaContextWatcher *watcher) 01399 { 01400 #ifndef USE_ROS 01401 __watchers.remove_locked(watcher); 01402 #else 01403 __watchers.remove(watcher); 01404 #endif 01405 } 01406 01407 01409 void 01410 LuaContext::process_fam_events() 01411 { 01412 if ( __fam) __fam->process_events(); 01413 } 01414 01415 01416 void 01417 LuaContext::fam_event(const char *filename, unsigned int mask) 01418 { 01419 restart(); 01420 } 01421 01422 01423 } // end of namespace fawkes