LuaComponent.cpp
Go to the documentation of this file.
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


ocl
Author(s): OCL Development Team
autogenerated on Mon Sep 14 2015 14:21:46