OrocosComponentLibrary
2.7.0
|
00001 /* 00002 * Lua-RTT bindings. LuaComponent. 00003 * 00004 * (C) Copyright 2010 Markus Klotzbuecher 00005 * markus.klotzbuecher@mech.kuleuven.be 00006 * Department of Mechanical Engineering, 00007 * Katholieke Universiteit Leuven, Belgium. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public 00011 * License as published by the Free Software Foundation; 00012 * version 2 of the License. 00013 * 00014 * As a special exception, you may use this file as part of a free 00015 * software library without restriction. Specifically, if other files 00016 * instantiate templates or use macros or inline functions from this 00017 * file, or you compile this file and link it with other files to 00018 * produce an executable, this file does not by itself cause the 00019 * resulting executable to be covered by the GNU General Public 00020 * License. This exception does not however invalidate any other 00021 * reasons why the executable file might be covered by the GNU General 00022 * Public License. 00023 * 00024 * This library is distributed in the hope that it will be useful, 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00027 * Lesser General Public License for more details. 00028 * 00029 * You should have received a copy of the GNU General Public 00030 * License along with this library; if not, write to the Free Software 00031 * Foundation, Inc., 59 Temple Place, 00032 * Suite 330, Boston, MA 02111-1307 USA 00033 */ 00034 00035 #ifndef OCL_COMPONENT_ONLY 00036 00037 #include <rtt/rtt-config.h> 00038 #ifdef OS_RT_MALLOC 00039 // need access to all TLSF functions embedded in RTT 00040 #define ORO_MEMORY_POOL 00041 #include <rtt/os/tlsf/tlsf.h> 00042 #endif 00043 #include <rtt/os/main.h> 00044 #include <rtt/RTT.hpp> 00045 #include <rtt/Logger.hpp> 00046 #ifdef ORO_BUILD_LOGGING 00047 # ifndef OS_RT_MALLOC 00048 # warning "Logging needs rtalloc!" 00049 # endif 00050 #include <log4cpp/HierarchyMaintainer.hh> 00051 #include "logging/Category.hpp" 00052 #endif 00053 00054 extern "C" { 00055 #include "lua-repl.h" 00056 void dotty (lua_State *L); 00057 void l_message (const char *pname, const char *msg); 00058 int dofile (lua_State *L, const char *name); 00059 int dostring (lua_State *L, const char *s, const char *name); 00060 int main_args(lua_State *L, int argc, char **argv); 00061 00062 #include <sys/types.h> 00063 #include <sys/stat.h> 00064 #include <unistd.h> 00065 #include <wordexp.h> 00066 } 00067 #endif 00068 00069 #include "rtt.hpp" 00070 00071 #include <string> 00072 #include <rtt/os/main.h> 00073 #include <rtt/os/Mutex.hpp> 00074 #include <rtt/os/MutexLock.hpp> 00075 #include <rtt/TaskContext.hpp> 00076 #include <ocl/OCL.hpp> 00077 #if defined(LUA_RTT_CORBA) 00078 #include <rtt/transports/corba/TaskContextServer.hpp> 00079 #include <deployment/CorbaDeploymentComponent.hpp> 00080 #else 00081 #include <deployment/DeploymentComponent.hpp> 00082 #endif 00083 00084 #ifdef LUA_RTT_TLSF 00085 extern "C" { 00086 #include "tlsf_rtt.h" 00087 } 00088 #endif 00089 00090 #ifdef LUA_RTT_TLSF 00091 #define LuaComponent LuaTLSFComponent 00092 #else 00093 #define LuaComponent LuaComponent 00094 #endif 00095 00096 #define INIT_FILE "~/.rttlua" 00097 00098 using namespace std; 00099 using namespace RTT; 00100 using namespace Orocos; 00101 #if defined(LUA_RTT_CORBA) 00102 using namespace RTT::corba; 00103 #endif 00104 00105 namespace OCL 00106 { 00107 class LuaComponent : public TaskContext 00108 { 00109 protected: 00110 std::string lua_string; 00111 std::string lua_file; 00112 lua_State *L; 00113 os::MutexRecursive m; 00114 #if LUA_RTT_TLSF 00115 struct lua_tlsf_info tlsf_inf; 00116 #endif 00117 00118 public: 00119 LuaComponent(std::string name) 00120 : TaskContext(name, PreOperational) 00121 { 00122 os::MutexLock lock(m); 00123 #if LUA_RTT_TLSF 00124 if(tlsf_rtt_init_mp(&tlsf_inf, TLSF_INITIAL_POOLSIZE)) { 00125 Logger::log(Logger::Error) << "LuaComponent '" << name << ": failed to create tlsf pool (" 00126 << std::hex << TLSF_INITIAL_POOLSIZE << "bytes)" << endlog(); 00127 throw; 00128 } 00129 00130 L = lua_newstate(tlsf_alloc, &tlsf_inf); 00131 tlsf_inf.L = L; 00132 set_context_tlsf_info(&tlsf_inf); 00133 register_tlsf_api(L); 00134 #else 00135 L = luaL_newstate(); 00136 #endif 00137 if (L == NULL) { 00138 Logger::log(Logger::Error) << "LuaComponent '" << name 00139 << "': failed to allocate memory for Lua state" << endlog(); 00140 throw; 00141 } 00142 00143 lua_gc(L, LUA_GCSTOP, 0); 00144 luaL_openlibs(L); 00145 lua_gc(L, LUA_GCRESTART, 0); 00146 00147 /* setup rtt bindings */ 00148 lua_pushcfunction(L, luaopen_rtt); 00149 lua_call(L, 0, 0); 00150 00151 set_context_tc(this, L); 00152 00153 this->addProperty("lua_string", lua_string).doc("string of lua code to be executed during configureHook"); 00154 this->addProperty("lua_file", lua_file).doc("file with lua program to be executed during configuration"); 00155 00156 this->addOperation("exec_file", &LuaComponent::exec_file, this, OwnThread) 00157 .doc("load (and run) the given lua script") 00158 .arg("filename", "filename of the lua script"); 00159 00160 this->addOperation("exec_str", &LuaComponent::exec_str, this, OwnThread) 00161 .doc("evaluate the given string in the lua environment") 00162 .arg("lua-string", "string of lua code to evaluate"); 00163 00164 #ifdef LUA_RTT_TLSF 00165 this->addOperation("tlsf_incmem", &LuaComponent::tlsf_incmem, this, OwnThread) 00166 .doc("increase the TLSF memory pool") 00167 .arg("size", "size in bytes to add to pool"); 00168 #endif 00169 } 00170 00171 ~LuaComponent() 00172 { 00173 os::MutexLock lock(m); 00174 lua_close(L); 00175 #ifdef LUA_RTT_TLSF 00176 tlsf_rtt_free_mp(&tlsf_inf); 00177 #endif 00178 } 00179 00180 #ifdef LUA_RTT_TLSF 00181 bool tlsf_incmem(unsigned int size) 00182 { 00183 return tlsf_rtt_incmem(&tlsf_inf, size); 00184 } 00185 #endif 00186 00187 00188 bool exec_file(const std::string &file) 00189 { 00190 os::MutexLock lock(m); 00191 if (luaL_dofile(L, file.c_str())) { 00192 Logger::log(Logger::Error) << "LuaComponent '" << this->getName() << "': " << lua_tostring(L, -1) << endlog(); 00193 return false; 00194 } 00195 return true; 00196 } 00197 00198 bool exec_str(const std::string &str) 00199 { 00200 os::MutexLock lock(m); 00201 if (luaL_dostring(L, str.c_str())) { 00202 Logger::log(Logger::Error) << "LuaComponent '" << this->getName() << "': " << lua_tostring(L, -1) << endlog(); 00203 return false; 00204 } 00205 return true; 00206 } 00207 00208 #ifndef OCL_COMPONENT_ONLY 00209 void lua_repl() 00210 { 00211 os::MutexLock lock(m); 00212 dotty(L); 00213 } 00214 00215 int lua_repl(int argc, char **argv) 00216 { 00217 os::MutexLock lock(m); 00218 return main_args(L, argc, argv); 00219 } 00220 #endif 00221 bool configureHook() 00222 { 00223 if(!lua_string.empty()) 00224 exec_str(lua_string); 00225 00226 if(!lua_file.empty()) 00227 exec_file(lua_file); 00228 return call_func(L, "configureHook", this, 0, 1); 00229 } 00230 00231 bool activateHook() 00232 { 00233 os::MutexLock lock(m); 00234 return call_func(L, "activateHook", this, 0, 1); 00235 } 00236 00237 bool startHook() 00238 { 00239 os::MutexLock lock(m); 00240 return call_func(L, "startHook", this, 0, 1); 00241 } 00242 00243 void updateHook() 00244 { 00245 os::MutexLock lock(m); 00246 call_func(L, "updateHook", this, 0, 0); 00247 } 00248 00249 void stopHook() 00250 { 00251 os::MutexLock lock(m); 00252 call_func(L, "stopHook", this, 0, 0); 00253 } 00254 00255 void cleanupHook() 00256 { 00257 os::MutexLock lock(m); 00258 call_func(L, "cleanupHook", this, 0, 0); 00259 } 00260 00261 void errorHook() 00262 { 00263 os::MutexLock lock(m); 00264 call_func(L, "errorHook", this, 0, 0); 00265 } 00266 }; 00267 } 00268 00269 00270 #ifndef OCL_COMPONENT_ONLY 00271 00272 int ORO_main(int argc, char** argv) 00273 { 00274 struct stat stb; 00275 wordexp_t init_exp; 00276 00277 #ifdef ORO_BUILD_RTALLOC 00278 size_t memSize = ORO_DEFAULT_RTALLOC_SIZE; 00279 void* rtMem = 0; 00280 size_t freeMem = 0; 00281 if (0 < memSize) 00282 { 00283 // don't calloc() as is first thing TLSF does. 00284 rtMem = malloc(memSize); 00285 assert(0 != rtMem); 00286 freeMem = init_memory_pool(memSize, rtMem); 00287 if ((size_t)-1 == freeMem) 00288 { 00289 cerr << "Invalid memory pool size of " << memSize 00290 << " bytes (TLSF has a several kilobyte overhead)." << endl; 00291 free(rtMem); 00292 return -1; 00293 } 00294 cout << "Real-time memory: " << freeMem << " bytes free of " 00295 << memSize << " allocated." << endl; 00296 } 00297 #endif // ORO_BUILD_RTALLOC 00298 00299 #ifdef ORO_BUILD_LOGGING 00300 log4cpp::HierarchyMaintainer::set_category_factory( 00301 OCL::logging::Category::createOCLCategory); 00302 #endif 00303 00304 LuaComponent lua("lua"); 00305 DeploymentComponent * dc = 0; 00306 00307 #if defined(LUA_RTT_CORBA) 00308 int orb_argc = argc; 00309 char** orb_argv = 0; 00310 char* orb_sep = 0; 00311 00312 /* find the "--" separator */ 00313 while(orb_argc) { 00314 if(0 == strcmp("--", argv[argc - orb_argc])) { 00315 orb_sep = argv[argc - orb_argc]; 00316 argv[argc - orb_argc] = argv[0]; 00317 orb_argv = &argv[argc - orb_argc]; 00318 argc -= orb_argc; 00319 break; 00320 } 00321 orb_argc--; 00322 } 00323 00324 /* if the "--" separator is found perhaps we have orb arguments */ 00325 if(orb_argc) { 00326 try { 00327 TaskContextServer::InitOrb(orb_argc, orb_argv); 00328 00329 dc = new CorbaDeploymentComponent("Deployer"); 00330 00331 TaskContextServer::Create( dc, true, true ); 00332 00333 // The orb thread accepts incomming CORBA calls. 00334 TaskContextServer::ThreadOrb(); 00335 } 00336 catch( CORBA::Exception &e ) { 00337 log(Error) << argv[0] <<" ORO_main : CORBA exception raised!" << Logger::nl; 00338 log() << CORBA_EXCEPTION_INFO(e) << endlog(); 00339 if(dc) 00340 { 00341 delete dc; 00342 dc = 0; 00343 } 00344 } catch (...) { 00345 log(Error) << "Uncaught exception." << endlog(); 00346 if(dc) 00347 { 00348 delete dc; 00349 dc = 0; 00350 } 00351 } 00352 00353 argv[argc] = dc?NULL:orb_sep; 00354 } 00355 00356 /* fallback to the default deployer if corba have failed to provide one */ 00357 if(!dc) 00358 #endif 00359 dc = new DeploymentComponent("Deployer"); 00360 00361 lua.connectPeers(dc); 00362 00363 /* run init file */ 00364 wordexp(INIT_FILE, &init_exp, 0); 00365 if(stat(init_exp.we_wordv[0], &stb) != -1) { 00366 if((stb.st_mode & S_IFMT) != S_IFREG) 00367 cout << "rttlua: warning: init file " << init_exp.we_wordv[0] << " is not a regular file" << endl; 00368 else 00369 lua.exec_file(init_exp.we_wordv[0]); 00370 } 00371 wordfree(&init_exp); 00372 00373 lua.lua_repl(argc, argv); 00374 00375 #if defined(LUA_RTT_CORBA) 00376 if(orb_argc) { 00377 TaskContextServer::ShutdownOrb(); 00378 TaskContextServer::DestroyOrb(); 00379 } 00380 #endif 00381 00382 delete dc; 00383 00384 #ifdef ORO_BUILD_LOGGING 00385 log4cpp::HierarchyMaintainer::getDefaultMaintainer().shutdown(); 00386 log4cpp::HierarchyMaintainer::getDefaultMaintainer().deleteAllCategories(); 00387 #endif 00388 00389 #ifdef ORO_BUILD_RTALLOC 00390 if (0 != rtMem) 00391 { 00392 std::cout << "TLSF bytes allocated=" << memSize 00393 << " overhead=" << (memSize - freeMem) 00394 << " max-used=" << get_max_size(rtMem) 00395 << " currently-used=" << get_used_size(rtMem) 00396 << " still-allocated=" << (get_used_size(rtMem) - (memSize - freeMem)) 00397 << "\n"; 00398 00399 destroy_memory_pool(rtMem); 00400 free(rtMem); 00401 } 00402 #endif 00403 return 0; 00404 } 00405 00406 #else 00407 00408 #include "ocl/Component.hpp" 00409 00410 ORO_CREATE_COMPONENT( OCL::LuaComponent ) 00411 #endif