$search
00001 /* 00002 * Lua-RTT bindings 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 #include "rtt.hpp" 00036 00037 using namespace std; 00038 using namespace RTT; 00039 using namespace RTT::detail; 00040 using namespace RTT::base; 00041 using namespace RTT::internal; 00042 00043 static TaskContext* __getTC(lua_State*); 00044 00045 #define DEBUG 00046 00047 #ifdef MSVC 00048 #ifdef DEBUG 00049 # define _DBG(fmt, ...) printf("%s:%d\t" fmt "\n", __FUNCTION__, __LINE__, __VA_ARGS__) 00050 #else 00051 # define _DBG(fmt, ...) do { } while(0); 00052 #endif 00053 #else 00054 #ifdef DEBUG 00055 # define _DBG(fmt, args...) printf("%s:%d\t" fmt "\n", __FUNCTION__, __LINE__, ##args) 00056 #else 00057 # define _DBG(fmt, args...) do { } while(0); 00058 #endif 00059 #endif 00060 00061 /* 00062 * Inspired by tricks from here: http://lua-users.org/wiki/DoItYourselfCppBinding 00063 */ 00064 00065 /* overloading new */ 00066 void* operator new(size_t size, lua_State* L, const char* mt) 00067 { 00068 void* ptr = lua_newuserdata(L, size); 00069 luaL_getmetatable(L, mt); 00070 /* assert(lua_istable(L, -1)) */ /* if you're paranoid */ 00071 lua_setmetatable(L, -2); 00072 return ptr; 00073 } 00074 00075 /* 00076 * luaM_pushobject_mt(L, "Port", InputPortInterface )(ctr_arg,...) 00077 * expands to 00078 * new(L, "Port") InputPortInterface(ctr_arg,...) 00079 */ 00080 00081 #define luaM_pushobject(L, T) new(L, #T) T 00082 #define luaM_pushobject_mt(L, MT, T) new(L, MT) T 00083 00084 /* return udata ptr or fail if wrong metatable */ 00085 #define luaM_checkudata(L, pos, T) reinterpret_cast<T*>(luaL_checkudata((L), (pos), #T)) 00086 #define luaM_checkudata_mt(L, pos, MT, T) reinterpret_cast<T*>(luaL_checkudata((L), (pos), MT)) 00087 00088 /* return udata ptr or NULL if wrong metatable */ 00089 #define luaM_testudata(L, pos, T) (T*) (luaL_testudata((L), (pos), #T)) 00090 #define luaM_testudata_mt(L, pos, MT, T) (T*) (luaL_testudata((L), (pos), MT)) 00091 00092 /* 00093 * boxed variants 00094 */ 00095 00096 /* return boxed udata ptr or fail if wrong metatable */ 00097 #define luaM_checkudata_bx(L, pos, T) (T**) (luaL_checkudata((L), (pos), #T)) 00098 #define luaM_checkudata_mt_bx(L, pos, MT, T) (T**) (luaL_checkudata((L), (pos), MT)) 00099 00100 /* return udata ptr or NULL if wrong metatable */ 00101 #define luaM_testudata_bx(L, pos, T) (T**) (luaL_testudata((L), (pos), #T)) 00102 #define luaM_testudata_mt_bx(L, pos, MT, T) (T**) (luaL_testudata((L), (pos), MT)) 00103 00104 /* generate a function to push boxed pointers to lua */ 00105 #define gen_push_bxptr(name, MT, T) \ 00106 static void name(lua_State *L, T* ptr) \ 00107 { \ 00108 T** ptrptr = (T**) lua_newuserdata(L, sizeof(T*)); \ 00109 *ptrptr = ptr; \ 00110 luaL_getmetatable(L, MT); \ 00111 lua_setmetatable(L, -2); \ 00112 } \ 00113 00114 /* template for generating GC function */ 00115 template<typename T> 00116 int GCMethod(lua_State* L) 00117 { 00118 reinterpret_cast<T*>(lua_touserdata(L, 1))->~T(); 00119 return 0; 00120 } 00121 00122 00123 /*************************************************************** 00124 * Some generic helpers 00125 ***************************************************************/ 00126 00127 /* test if userdata on position ud has metatable tname */ 00128 void* luaL_testudata (lua_State *L, int ud, const char *tname) 00129 { 00130 void *p = lua_touserdata(L, ud); 00131 00132 if (p == NULL) 00133 goto out; 00134 00135 if (!lua_getmetatable(L, ud)) { 00136 p = NULL; 00137 goto out; 00138 } 00139 00140 /* it has a MT, is it the right one? */ 00141 lua_pushstring(L, tname); 00142 lua_rawget(L, LUA_REGISTRYINDEX); 00143 00144 if (!lua_rawequal(L, -1, -2)) 00145 p = NULL; 00146 00147 lua_pop(L, 2); /* remove both metatables */ 00148 out: 00149 return p; 00150 } 00151 00152 00153 void push_vect_str(lua_State *L, const std::vector<std::string> &v) 00154 { 00155 int key = 1; 00156 lua_createtable(L, v.size(), 0); 00157 00158 for(vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) { 00159 lua_pushstring(L, it->c_str()); 00160 lua_rawseti(L, -2, key++); 00161 } 00162 } 00163 00164 /* forw decl */ 00165 static void Variable_fromlua(lua_State *L, DataSourceBase::shared_ptr& dsb, int valind); 00166 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const types::TypeInfo* ti, int valind); 00167 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const char* type, int valind); 00168 00169 /*************************************************************** 00170 * Variable (DataSourceBase) 00171 ***************************************************************/ 00172 00173 static const TypeInfo* ti_lookup(lua_State *L, const char *name) 00174 { 00175 #ifndef TYPEINFO_CACHING 00176 return types::TypeInfoRepository::Instance()->type(name); 00177 #else 00178 /* name-> TypeInfo* cache */ 00179 int top = lua_gettop(L); 00180 const TypeInfo* ti; 00181 00182 /* try lookup */ 00183 lua_pushstring(L, "typeinfo_cache"); 00184 lua_rawget(L, LUA_REGISTRYINDEX); 00185 00186 if(lua_type(L, -1) == LUA_TTABLE) 00187 goto table_on_top; 00188 00189 /* first lookup, create table */ 00190 lua_pop(L, 1); /* pop nil */ 00191 lua_newtable(L); /* stays on top after the next three lines */ 00192 lua_pushstring(L, "typeinfo_cache"); /* key */ 00193 lua_pushvalue(L, -2); /* duplicates table */ 00194 lua_rawset(L, LUA_REGISTRYINDEX); /* REG['typeinfo_cache']={} */ 00195 00196 table_on_top: 00197 /* try to lookup name in table */ 00198 lua_pushstring(L, name); 00199 lua_rawget(L, -2); 00200 00201 if(lua_type(L, -1) != LUA_TLIGHTUSERDATA) 00202 goto cache_miss; 00203 00204 ti = (const TypeInfo*) lua_touserdata(L, -1); 00205 goto out; 00206 00207 cache_miss: 00208 lua_pop(L, 1); /* pop the nil */ 00209 ti = types::TypeInfoRepository::Instance()->type(name); 00210 if (ti) { // only save if type exists ! 00211 lua_pushstring(L, name); 00212 lua_pushlightuserdata(L, (void*) ti); 00213 lua_rawset(L, -3); 00214 } 00215 out: 00216 /* everyone happy! */ 00217 lua_settop(L, top); 00218 return ti; 00219 #endif /* TYPEINFO_CACHING */ 00220 } 00221 00222 /* helper, check if two type names are alias to the same TypeInfo */ 00223 static bool __typenames_cmp(lua_State *L, const char* type1, const char* type2) 00224 { 00225 const types::TypeInfo *ti1 = ti_lookup(L, type1); 00226 const types::TypeInfo *ti2 = ti_lookup(L, type2); 00227 return ti1 == ti2; 00228 } 00229 00230 static bool __typenames_cmp(lua_State *L, const types::TypeInfo *ti1, const char* type2) 00231 { 00232 const types::TypeInfo *ti2 = ti_lookup(L, type2); 00233 return ti1 == ti2; 00234 } 00235 00236 /* helper, check if a dsb is of type type. Works also if dsb is known 00237 under an alias of type */ 00238 static bool Variable_is_a(lua_State *L, const types::TypeInfo *ti1, const char* type) 00239 { 00240 const types::TypeInfo *ti2 = ti_lookup(L, type); 00241 return ti1 == ti2; 00242 } 00243 00244 /* helper, check if a variable is basic, that is _tolua will succeed */ 00245 static bool __Variable_isbasic(lua_State *L, DataSourceBase::shared_ptr &dsb) 00246 { 00247 const types::TypeInfo *ti = dsb->getTypeInfo(); 00248 00249 if ( Variable_is_a(L, ti, "bool") || 00250 Variable_is_a(L, ti, "double") || 00251 Variable_is_a(L, ti, "float") || 00252 Variable_is_a(L, ti, "uint") || 00253 Variable_is_a(L, ti, "int") || 00254 Variable_is_a(L, ti, "long") || 00255 Variable_is_a(L, ti, "char") || 00256 Variable_is_a(L, ti, "uint8") || Variable_is_a(L, ti, "int8") || 00257 Variable_is_a(L, ti, "uint16") || Variable_is_a(L, ti, "int16") || 00258 Variable_is_a(L, ti, "uint32") || Variable_is_a(L, ti, "int32") || 00259 Variable_is_a(L, ti, "uint64") || Variable_is_a(L, ti, "int64") || 00260 Variable_is_a(L, ti, "string") || 00261 Variable_is_a(L, ti, "void")) 00262 return true; 00263 else 00264 return false; 00265 } 00266 00267 static int Variable_isbasic(lua_State *L) 00268 { 00269 DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); 00270 lua_pushboolean(L, __Variable_isbasic(L, dsb)); 00271 return 1; 00272 } 00273 00274 00275 /* 00276 * converts a DataSourceBase to the corresponding Lua value and pushes 00277 * that on the stack. 00278 */ 00279 static int __Variable_tolua(lua_State *L, DataSourceBase::shared_ptr dsb) 00280 { 00281 DataSourceBase *ds = dsb.get(); 00282 const types::TypeInfo* ti = dsb->getTypeInfo(); 00283 assert(ds); 00284 00285 if(Variable_is_a(L, ti, "bool")) { // bool 00286 DataSource<bool>* dsb = DataSource<bool>::narrow(ds); 00287 if(dsb) lua_pushboolean(L, dsb->get()); 00288 else goto out_nodsb; 00289 } else if (Variable_is_a(L, ti, "float")) { // float 00290 DataSource<float>* dsb = DataSource<float>::narrow(ds); 00291 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00292 else goto out_nodsb; 00293 } else if (Variable_is_a(L, ti, "double")) { // double 00294 DataSource<double>* dsb = DataSource<double>::narrow(ds); 00295 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00296 else goto out_nodsb; 00297 } else if (Variable_is_a(L, ti, "uint8")) { // uint8_t 00298 DataSource<uint8_t>* dsb = DataSource<uint8_t>::narrow(ds); 00299 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00300 else goto out_nodsb; 00301 } else if (Variable_is_a(L, ti, "int8")) { // int8_t 00302 DataSource<int8_t>* dsb = DataSource<int8_t>::narrow(ds); 00303 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00304 else goto out_nodsb; 00305 } else if (Variable_is_a(L, ti, "uint16")) { // uint16_t 00306 DataSource<uint16_t>* dsb = DataSource<uint16_t>::narrow(ds); 00307 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00308 else goto out_nodsb; 00309 } else if (Variable_is_a(L, ti, "int16")) { // int16_t 00310 DataSource<int16_t>* dsb = DataSource<int16_t>::narrow(ds); 00311 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00312 else goto out_nodsb; 00313 } else if (Variable_is_a(L, ti, "uint32")) { // uint32_t 00314 DataSource<uint32_t>* dsb = DataSource<uint32_t>::narrow(ds); 00315 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00316 else goto out_nodsb; 00317 } else if (Variable_is_a(L, ti, "int32")) { // int32_t 00318 DataSource<int32_t>* dsb = DataSource<int32_t>::narrow(ds); 00319 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00320 else goto out_nodsb; 00321 } else if (Variable_is_a(L, ti, "uint64")) { // uint64_t 00322 DataSource<uint64_t>* dsb = DataSource<uint64_t>::narrow(ds); 00323 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00324 else goto out_nodsb; 00325 } else if (Variable_is_a(L, ti, "int64")) { // int64_t 00326 DataSource<int64_t>* dsb = DataSource<int64_t>::narrow(ds); 00327 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00328 else goto out_nodsb; 00329 } else if (Variable_is_a(L, ti, "uint")) { // uint 00330 DataSource<unsigned int>* dsb = DataSource<unsigned int>::narrow(ds); 00331 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00332 else goto out_nodsb; 00333 } else if (Variable_is_a(L, ti, "long")) { //long 00334 DataSource<long>* dsb = DataSource<long>::narrow(ds); 00335 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00336 else goto out_nodsb; 00337 } else if (Variable_is_a(L, ti, "int")) { // int 00338 DataSource<int>* dsb = DataSource<int>::narrow(ds); 00339 if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get())); 00340 else goto out_nodsb; 00341 } else if (Variable_is_a(L, ti, "char")) { // char 00342 DataSource<char>* dsb = DataSource<char>::narrow(ds); 00343 char c = dsb->get(); 00344 if(dsb) lua_pushlstring(L, &c, 1); 00345 else goto out_nodsb; 00346 } else if (Variable_is_a(L, ti, "string")) { //string 00347 DataSource<std::string>* dsb = DataSource<std::string>::narrow(ds); 00348 if(dsb) lua_pushlstring(L, dsb->get().c_str(), dsb->get().size()); 00349 else goto out_nodsb; 00350 } else if (Variable_is_a(L, ti, "void")) { 00351 DataSource<void>* dsb = DataSource<void>::narrow(ds); 00352 if(dsb) lua_pushnil(L); 00353 else goto out_nodsb; 00354 } else { 00355 goto out_conv_err; 00356 } 00357 00358 /* all ok */ 00359 return 1; 00360 00361 out_conv_err: 00362 luaL_error(L, "Variable.tolua: can't convert type %s", dsb->getTypeName().c_str()); 00363 return 0; 00364 00365 out_nodsb: 00366 luaL_error(L, "Variable.tolua: narrow failed for %s Variable", dsb->getTypeName().c_str()); 00367 return 0; 00368 } 00369 00370 static int Variable_tolua(lua_State *L) 00371 { 00372 DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); 00373 return __Variable_tolua(L, dsb); 00374 } 00375 00376 /* Function takes a DSB, that is also expected on the top of the 00377 * stack. If the DSB is basic, it replaces the dsb with the 00378 * corresponding Lua value. Otherwise it does nothing, leaving the DSB 00379 * on the top of the stack. 00380 */ 00381 static void Variable_coerce(lua_State *L, DataSourceBase::shared_ptr dsb) 00382 { 00383 if (__Variable_isbasic(L, dsb)) { 00384 lua_pop(L, 1); 00385 __Variable_tolua(L, dsb); 00386 } 00387 } 00388 00389 /* this function takes a dsb and either pushes it as a Lua type if the 00390 * dsb is basic or otherwise as at Variable 00391 */ 00392 static void Variable_push_coerce(lua_State *L, DataSourceBase::shared_ptr dsb) 00393 { 00394 if (__Variable_isbasic(L, dsb)) 00395 __Variable_tolua(L, dsb); 00396 else 00397 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(dsb); 00398 00399 } 00400 00401 static int Variable_getTypes(lua_State *L) 00402 { 00403 push_vect_str(L, Types()->getTypes()); 00404 return 1; 00405 } 00406 00407 static int Variable_getMemberNames(lua_State *L) 00408 { 00409 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00410 push_vect_str(L, (*dsbp)->getMemberNames()); 00411 return 1; 00412 } 00413 00414 static int Variable_tolightuserdata(lua_State *L) 00415 { 00416 DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); 00417 lua_pushlightuserdata(L, dsb->getRawPointer()); 00418 return 1; 00419 } 00420 00421 00422 /* caching of DSB members 00423 * lookup of DSB using getMember and caches result. 00424 * returns DSB (or nil if lookup fails) on top of stack. 00425 */ 00426 static DataSourceBase::shared_ptr lookup_member(lua_State *L, DataSourceBase::shared_ptr parent, const char* mem) 00427 { 00428 DataSourceBase *varptr; 00429 DataSourceBase::shared_ptr *dsbp; 00430 DataSourceBase::shared_ptr memdsb; 00431 int top = lua_gettop(L); 00432 00433 varptr = parent.get(); 00434 00435 lua_pushlightuserdata(L, (void*) varptr); 00436 lua_rawget(L, LUA_REGISTRYINDEX); 00437 00438 if(lua_type(L, -1) == LUA_TNIL) 00439 goto cache_miss; 00440 00441 lua_pushstring(L, mem); 00442 lua_rawget(L, -2); 00443 00444 if ((dsbp = luaM_testudata_mt(L, -1, "Variable", DataSourceBase::shared_ptr)) != NULL) { 00445 memdsb=*dsbp; 00446 goto out; 00447 } 00448 00449 lua_pop(L, 1); /* pop nil from table lookup */ 00450 00451 cache_miss: 00452 /* slowpath */ 00453 memdsb = parent->getMember(mem); 00454 00455 if(memdsb == 0) 00456 goto out; 00457 00458 /* if nil is on top of stack, we have to create a new table */ 00459 if(lua_type(L, -1) == LUA_TNIL) { 00460 lua_newtable(L); /* member lookup tab for this Variable */ 00461 lua_pushlightuserdata(L, (void*) varptr); /* index for REGISTRY */ 00462 lua_pushvalue(L, -2); /* duplicates table */ 00463 lua_rawset(L, LUA_REGISTRYINDEX); /* REG[varptr]=newtab */ 00464 } 00465 00466 /* cache dsb in table */ 00467 lua_pushstring(L, mem); 00468 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(memdsb); 00469 lua_rawset(L, -3); /* newtab[mem]=memdsb, top is newtab */ 00470 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(memdsb); 00471 00472 out: 00473 lua_replace(L, top+1); // make new var top of stack 00474 lua_settop(L, top+1); 00475 00476 return memdsb; 00477 } 00478 00479 /* set reg[varptr] to nil so table will be garbage collected */ 00480 static void cache_clear(lua_State *L, DataSourceBase *varptr) 00481 { 00482 lua_pushlightuserdata(L, (void*) varptr); 00483 lua_pushnil(L); 00484 lua_rawset(L, LUA_REGISTRYINDEX); 00485 } 00486 00487 static int Variable_getMember(lua_State *L) 00488 { 00489 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00490 DataSourceBase::shared_ptr memdsb; 00491 const char *mem = luaL_checkstring(L, 2); 00492 00493 if ((memdsb = lookup_member(L, *dsbp, mem)) == 0) 00494 luaL_error(L, "Variable.getMember: indexing failed, no member %s", mem); 00495 else 00496 Variable_coerce(L, memdsb); 00497 00498 return 1; 00499 } 00500 00501 static int Variable_getMemberRaw(lua_State *L) 00502 { 00503 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00504 DataSourceBase::shared_ptr memdsb; 00505 const char *mem = luaL_checkstring(L, 2); 00506 00507 if ((memdsb = lookup_member(L, (*dsbp), mem)) == 0) 00508 luaL_error(L, "Variable.getMemberRaw: indexing failed, no member %s", mem); 00509 00510 /* else: Variable is already on top of stack */ 00511 00512 return 1; 00513 } 00514 00515 static int Variable_update(lua_State *L) 00516 { 00517 int ret; 00518 DataSourceBase::shared_ptr dsb; 00519 DataSourceBase::shared_ptr *dsbp; 00520 DataSourceBase::shared_ptr self = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); 00521 00522 if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) { 00523 dsb = *dsbp; 00524 ret = self->update(dsb.get()); 00525 if (!ret) luaL_error(L, "Variable.assign: assignment failed"); 00526 } else { 00527 Variable_fromlua(L, self, 2); 00528 } 00529 00530 return 0; 00531 } 00532 00533 /* create variable */ 00534 static int Variable_create(lua_State *L) 00535 { 00536 const char *type; 00537 type = luaL_checkstring(L, 1); 00538 00539 if(!strcmp(type, "void")) 00540 luaL_error(L, "Variable.new: can't create void variable"); 00541 00542 TypeInfo* ti = Types()->type(type); 00543 00544 if(ti==0) 00545 luaL_error(L, "Variable.new: unknown type %s", type); 00546 00547 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(ti->buildValue()); 00548 return 1; 00549 } 00550 00551 #define CONVERT_TO_NUMBER(CTGT) \ 00552 lua_Number x; \ 00553 if (luatype == LUA_TNUMBER) x = lua_tonumber(L, valind); \ 00554 else goto out_conv_err; \ 00555 AssignableDataSource<CTGT> *ads = ValueDataSource<CTGT>::narrow(dsb.get()); \ 00556 if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to %s.", #CTGT ); \ 00557 ads->set((CTGT) x)\ 00558 00559 /* Try to convert the Lua value on stack at valind to given DSB 00560 * if it returns, evertthing is ok */ 00561 static void Variable_fromlua(lua_State *L, DataSourceBase::shared_ptr& dsb, int valind) 00562 { 00563 const types::TypeInfo* ti = dsb->getTypeInfo(); 00564 00565 luaL_checkany(L, valind); 00566 int luatype = lua_type(L, valind); /* type of lua variable */ 00567 00568 if(__typenames_cmp(L, ti, "bool")) { 00569 lua_Number x; 00570 if(luatype == LUA_TBOOLEAN) 00571 x = (lua_Number) lua_toboolean(L, valind); 00572 else if (luatype == LUA_TNUMBER) 00573 x = lua_tonumber(L, valind); 00574 else 00575 goto out_conv_err; 00576 00577 AssignableDataSource<bool> *ads = ValueDataSource<bool>::narrow(dsb.get()); 00578 if (ads == NULL) 00579 luaL_error(L, "Variable_fromlua: failed to narrow target dsb to bool"); 00580 ads->set((bool) x); 00581 } 00582 else if (__typenames_cmp(L, ti, "uint")) { CONVERT_TO_NUMBER(unsigned int); } 00583 else if (__typenames_cmp(L, ti, "int")) { CONVERT_TO_NUMBER(int); } 00584 else if (__typenames_cmp(L, ti, "double")) { CONVERT_TO_NUMBER(double); } 00585 else if (__typenames_cmp(L, ti, "long")) { CONVERT_TO_NUMBER(double); } 00586 else if (__typenames_cmp(L, ti, "uint8")) { CONVERT_TO_NUMBER(uint8_t); } 00587 else if (__typenames_cmp(L, ti, "int8")) { CONVERT_TO_NUMBER(int8_t); } 00588 else if (__typenames_cmp(L, ti, "uint16")) { CONVERT_TO_NUMBER(uint16_t); } 00589 else if (__typenames_cmp(L, ti, "int16")) { CONVERT_TO_NUMBER(int16_t); } 00590 else if (__typenames_cmp(L, ti, "uint32")) { CONVERT_TO_NUMBER(uint32_t); } 00591 else if (__typenames_cmp(L, ti, "int32")) { CONVERT_TO_NUMBER(int32_t); } 00592 else if (__typenames_cmp(L, ti, "uint64")) { CONVERT_TO_NUMBER(uint64_t); } 00593 else if (__typenames_cmp(L, ti, "int64")) { CONVERT_TO_NUMBER(int64_t); } 00594 else if (__typenames_cmp(L, ti, "float")) { CONVERT_TO_NUMBER(float); } 00595 00596 else if (__typenames_cmp(L, ti, "char")) { 00597 const char *x; 00598 size_t l; 00599 if (luatype == LUA_TSTRING) x = lua_tolstring(L, valind, &l); 00600 else goto out_conv_err; 00601 AssignableDataSource<char> *ads = ValueDataSource<char>::narrow(dsb.get()); 00602 if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to char"); 00603 ads->set((char) x[0]); 00604 00605 } else if (__typenames_cmp(L, ti, "string")) { 00606 const char *x; 00607 if (luatype == LUA_TSTRING) x = lua_tostring(L, valind); 00608 else goto out_conv_err; 00609 AssignableDataSource<std::string> *ads = ValueDataSource<std::string>::narrow(dsb.get()); 00610 if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to std::string"); 00611 ads->set((std::string) x); 00612 00613 } else { 00614 goto out_conv_err; 00615 } 00616 00617 /* everybody happy */ 00618 return; 00619 00620 out_conv_err: 00621 luaL_error(L, "__lua_todsb: can't convert lua %s to %s variable", 00622 lua_typename(L, luatype), ti->getTypeName().c_str()); 00623 return; 00624 } 00625 00626 /* Create a DSB of RTT ti from the Lua value at stack[valind] 00627 * This one will create a dsb - NRT!*/ 00628 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const types::TypeInfo *ti, int valind) 00629 { 00630 DataSourceBase::shared_ptr dsb = ti->buildValue(); 00631 Variable_fromlua(L, dsb, valind); 00632 return dsb; 00633 } 00634 00635 /* Create a DSB of RTT type 'type' from the Lua value at stack[valind] 00636 * This one will create a dsb - NRT! 00637 * This one should be avoided, to reduce needless name-ti lookups. 00638 * preferred variant is the one taking TypeInfo * as second arg */ 00639 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const char* type, int valind) 00640 { 00641 const types::TypeInfo* ti = ti_lookup(L, type); 00642 if(!ti) luaL_error(L, "Variable_fromlua: %s is not a known type. Load typekit?", type); 00643 return Variable_fromlua(L, ti, valind); 00644 } 00645 00646 00647 static int Variable_create_ival(lua_State *L, int typeind, int valind) 00648 { 00649 DataSourceBase::shared_ptr dsb; 00650 luaL_checkany(L, valind); 00651 const char* type = luaL_checkstring(L, typeind); /* target dsb type */ 00652 dsb = Variable_fromlua(L, type, valind); 00653 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(dsb); 00654 return 1; 00655 } 00656 00657 static int Variable_new(lua_State *L) 00658 { 00659 int argc = lua_gettop(L); 00660 if(argc == 1) 00661 return Variable_create(L); 00662 else if(argc == 2) 00663 return Variable_create_ival(L, 1, 2); 00664 else 00665 luaL_error(L, "Variable.new: invalid number of args"); 00666 00667 return 0; 00668 } 00669 00670 static int Variable_toString(lua_State *L) 00671 { 00672 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00673 lua_pushstring(L, ((*dsbp)->toString()).c_str()); 00674 return 1; 00675 } 00676 00677 static int Variable_getType(lua_State *L) 00678 { 00679 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00680 lua_pushstring(L, (*dsbp)->getType().c_str()); 00681 return 1; 00682 } 00683 00684 static int Variable_getTypeIdName(lua_State *L) 00685 { 00686 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00687 lua_pushstring(L, (*dsbp)->getTypeInfo()->getTypeIdName()); 00688 return 1; 00689 } 00690 00691 static int Variable_getTypeName(lua_State *L) 00692 { 00693 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00694 lua_pushstring(L, (*dsbp)->getTypeName().c_str()); 00695 return 1; 00696 } 00697 00698 static int Variable_resize(lua_State *L) 00699 { 00700 int size; 00701 DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr); 00702 size = luaL_checknumber(L, 2); 00703 const TypeInfo *ti = (*dsbp)->getTypeInfo(); 00704 lua_pushboolean(L, ti->resize(*dsbp, size)); 00705 return 1; 00706 } 00707 00708 00709 /* 00710 * Operators 00711 */ 00712 static int Variable_unm(lua_State *L) 00713 { 00714 types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); 00715 DataSourceBase::shared_ptr arg = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); 00716 DataSourceBase::shared_ptr res = opreg->applyUnary("-", arg.get()); 00717 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res); 00718 return 1; 00719 } 00720 00721 00722 /* don't try this at home */ 00723 #define gen_opmet(name, op) \ 00724 static int name(lua_State *L) \ 00725 { \ 00726 DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); \ 00727 DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); \ 00728 types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); \ 00729 DataSourceBase *res = opreg->applyBinary(#op, arg1.get(), arg2.get()); \ 00730 if(res == 0) \ 00731 luaL_error(L , "%s (operator %s) failed", #name, #op); \ 00732 res->evaluate(); \ 00733 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res); \ 00734 return 1; \ 00735 } \ 00736 00737 gen_opmet(Variable_add, +) 00738 gen_opmet(Variable_sub, -) 00739 gen_opmet(Variable_mul, *) 00740 gen_opmet(Variable_div, /) 00741 gen_opmet(Variable_mod, %) 00742 gen_opmet(Variable_pow, ^) 00743 00744 /* these flavors convert the boolean return dsb to a lua bool */ 00745 #define gen_opmet_bool(name, op) \ 00746 static int name(lua_State *L) \ 00747 { \ 00748 DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); \ 00749 DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); \ 00750 types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); \ 00751 DataSourceBase *res = opreg->applyBinary(#op, arg1.get(), arg2.get()); \ 00752 if(res == 0) \ 00753 luaL_error(L , "%s (operator %s) failed", #name, #op); \ 00754 res->evaluate(); \ 00755 return __Variable_tolua(L, res); \ 00756 } \ 00757 00758 gen_opmet_bool(Variable_eq, ==) 00759 gen_opmet_bool(Variable_lt, <) 00760 gen_opmet_bool(Variable_le, <=) 00761 00762 static int Variable_opBinary(lua_State *L) 00763 { 00764 types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); 00765 const char *op = luaL_checkstring(L, 1); 00766 DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); 00767 DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 3, "Variable", DataSourceBase::shared_ptr)); 00768 DataSourceBase *res; 00769 00770 res = opreg->applyBinary(op, arg1.get(), arg2.get()); 00771 if(res == 0) 00772 luaL_error(L , "Variable.opBinary '%s' not applicable to args", op); 00773 00774 res->evaluate(); 00775 00776 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res); 00777 return 1; 00778 } 00779 00780 /* 00781 * this is a dispatcher which checks if the key is a method, otherwise 00782 * calls get for looking up the field. Inspired by 00783 * http://lua-users.org/wiki/ObjectProperties 00784 */ 00785 static int Variable_index(lua_State *L) 00786 { 00787 const char* key = luaL_checkstring(L, 2); 00788 00789 lua_getmetatable(L, 1); 00790 lua_getfield(L, -1, key); 00791 00792 /* Either key is name of a method in the metatable */ 00793 if(!lua_isnil(L, -1)) 00794 return 1; 00795 00796 /* ... or its a field access, so recall as self.get(self, value). */ 00797 lua_settop(L, 2); 00798 return Variable_getMember(L); 00799 } 00800 00801 static int Variable_newindex(lua_State *L) 00802 { 00803 DataSourceBase::shared_ptr *newvalp; 00804 DataSourceBase::shared_ptr newval; 00805 DataSourceBase::shared_ptr parent = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); 00806 const char* mem = luaL_checkstring(L, 2); 00807 00808 /* get dsb to be updated: we need its type before get-or-create'ing arg3 */ 00809 types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); 00810 DataSourceBase::shared_ptr curval; 00811 00812 if ((curval = lookup_member(L, parent, mem)) == 0) 00813 luaL_error(L, "Variable.newindex: indexing failed, no member %s", mem); 00814 00815 00816 /* assigning a DSB */ 00817 if ((newvalp = luaM_testudata_mt(L, 3, "Variable", DataSourceBase::shared_ptr)) != NULL) { 00818 newval = *newvalp; 00819 if(!curval->update(newval.get())) { 00820 luaL_error(L, "Variable.newindex: failed to assign %s to member %s of type %s", 00821 newval->getType().c_str(), mem, curval->getType().c_str()); 00822 } 00823 } else /* assigning basic type */ 00824 Variable_fromlua(L, curval, 3); 00825 return 1; 00826 } 00827 00828 // Why doesn't the following work: 00829 // static int Variable_gc(lua_State *L) 00830 // { 00831 // DataSourceBase::shared_ptr *dsbp = (DataSourceBase::shared_ptr*) lua_touserdata(L, 1); 00832 // cache_clear(L, dsbp->get()); 00833 // dsbp->~DataSourceBase::shared_ptr(); 00834 // return 0; 00835 // } 00836 00837 template<typename T> 00838 int VariableGC(lua_State* L) 00839 { 00840 T* dsbp = (T*) lua_touserdata(L, 1); 00841 cache_clear(L, dsbp->get()); 00842 reinterpret_cast<T*>(dsbp)->~T(); 00843 return 0; 00844 } 00845 00846 00847 static const struct luaL_Reg Variable_f [] = { 00848 { "new", Variable_new }, 00849 { "tolua", Variable_tolua }, 00850 { "isbasic", Variable_isbasic }, 00851 { "toString", Variable_toString }, 00852 { "getTypes", Variable_getTypes }, 00853 { "getType", Variable_getType }, 00854 { "getTypeName", Variable_getTypeName }, 00855 { "getTypeIdName", Variable_getTypeIdName }, 00856 { "getMemberNames", Variable_getMemberNames }, 00857 { "getMember", Variable_getMember }, 00858 { "getMemberRaw", Variable_getMemberRaw }, 00859 { "tolud", Variable_tolightuserdata }, 00860 { "resize", Variable_resize }, 00861 { "opBinary", Variable_opBinary }, 00862 { "assign", Variable_update }, /* assign seems a better name than update */ 00863 { "unm", Variable_unm }, 00864 { "add", Variable_add }, 00865 { "sub", Variable_sub }, 00866 { "mul", Variable_mul }, 00867 { "div", Variable_div }, 00868 { "mod", Variable_mod }, 00869 { "pow", Variable_pow }, 00870 { "eq", Variable_eq }, 00871 { "lt", Variable_lt }, 00872 { "le", Variable_le }, 00873 { NULL, NULL} 00874 }; 00875 00876 static const struct luaL_Reg Variable_m [] = { 00877 { "tolua", Variable_tolua }, 00878 { "isbasic", Variable_isbasic }, 00879 { "toString", Variable_toString }, 00880 { "getType", Variable_getType }, 00881 { "getTypeName", Variable_getTypeName }, 00882 { "getTypeIdName", Variable_getTypeIdName }, 00883 { "getMemberNames", Variable_getMemberNames }, 00884 { "getMember", Variable_getMember }, 00885 { "getMemberRaw", Variable_getMemberRaw }, 00886 { "tolud", Variable_tolightuserdata }, 00887 { "resize", Variable_resize }, 00888 { "opBinary", Variable_opBinary }, 00889 { "assign", Variable_update }, /* assign seems a better name than update */ 00890 { "__unm", Variable_unm }, 00891 { "__add", Variable_add }, 00892 { "__sub", Variable_sub }, 00893 { "__mul", Variable_mul }, 00894 { "__div", Variable_div }, 00895 { "__mod", Variable_mod }, 00896 { "__pow", Variable_pow }, 00897 { "__eq", Variable_eq }, 00898 { "__lt", Variable_lt }, 00899 { "__le", Variable_le }, 00900 { "__index", Variable_index }, 00901 { "__newindex", Variable_newindex }, 00902 // { "__gc", GCMethod<DataSourceBase::shared_ptr> }, 00903 // {"__gc", Variable_gc}, 00904 {"__gc", VariableGC<DataSourceBase::shared_ptr> }, 00905 { NULL, NULL} 00906 }; 00907 00908 00909 /*************************************************************** 00910 * Property (boxed) 00911 ***************************************************************/ 00912 00913 gen_push_bxptr(Property_push, "Property", PropertyBase) 00914 00915 static int Property_new(lua_State *L) 00916 { 00917 const char *type, *name, *desc; 00918 PropertyBase *pb; 00919 int argc = lua_gettop(L); 00920 type = luaL_checkstring(L, 1); 00921 00922 /* name and description are optional */ 00923 name = (argc > 1) ? luaL_checkstring(L, 2) : ""; 00924 desc = (argc > 2) ? luaL_checkstring(L, 3) : ""; 00925 00926 types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type); 00927 00928 if(!ti) 00929 luaL_error(L, "Property.new: unknown type %s", type); 00930 00931 pb = ti->buildProperty(name, desc); 00932 Property_push(L, pb); 00933 return 1; 00934 } 00935 00936 static int Property_get(lua_State *L) 00937 { 00938 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase)); 00939 Variable_push_coerce(L, pb->getDataSource()); 00940 return 1; 00941 } 00942 00943 static int Property_getRaw(lua_State *L) 00944 { 00945 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase)); 00946 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(pb->getDataSource()); 00947 return 1; 00948 } 00949 00950 static int Property_set(lua_State *L) 00951 { 00952 DataSourceBase::shared_ptr newdsb; 00953 DataSourceBase::shared_ptr *newdsbp; 00954 DataSourceBase::shared_ptr propdsb; 00955 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase)); 00956 propdsb = pb->getDataSource(); 00957 00958 /* assigning a DSB */ 00959 if ((newdsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) { 00960 newdsb = *newdsbp; 00961 if(!propdsb->update(newdsb.get())) 00962 luaL_error(L, "Property.set: failed to assign type %s to type %s", 00963 newdsb->getType().c_str(), propdsb->getType().c_str()); 00964 } else { /* assigning a Lua value */ 00965 Variable_fromlua(L, propdsb, 2); 00966 } 00967 return 1; 00968 } 00969 00970 static int Property_info(lua_State *L) 00971 { 00972 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase)); 00973 lua_newtable(L); 00974 lua_pushstring(L, "name"); lua_pushstring(L, pb->getName().c_str()); lua_rawset(L, -3); 00975 lua_pushstring(L, "desc"); lua_pushstring(L, pb->getDescription().c_str()); lua_rawset(L, -3); 00976 lua_pushstring(L, "type"); lua_pushstring(L, pb->getType().c_str()); lua_rawset(L, -3); 00977 return 1; 00978 } 00979 00980 #if NOT_USED_YET 00981 /* 00982 * Race condition if we collect properties: if we add this property to 00983 * a TC and our life ends before that of the TC, the property will be 00984 * deleted before the TaskContext. 00985 */ 00986 static int Property_gc(lua_State *L) 00987 { 00988 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase)); 00989 delete pb; 00990 return 0; 00991 } 00992 #endif 00993 00994 /* only explicit destruction allowed */ 00995 static int Property_del(lua_State *L) 00996 { 00997 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase)); 00998 delete pb; 00999 01000 /* this prevents calling rtt methods which would cause a crash */ 01001 luaL_getmetatable(L, "__dead__"); 01002 lua_setmetatable(L, -2); 01003 return 0; 01004 } 01005 01006 /* indexability of properties */ 01007 /* 01008 * this is a dispatcher which checks if the key is a method, otherwise 01009 * calls get for looking up the field. Inspired by 01010 * http://lua-users.org/wiki/ObjectProperties 01011 */ 01012 static int Property_index(lua_State *L) 01013 { 01014 const char* key = luaL_checkstring(L, 2); 01015 01016 lua_getmetatable(L, 1); 01017 lua_getfield(L, -1, key); /* this actually calls the method */ 01018 01019 /* Either key is name of a method in the metatable */ 01020 if(!lua_isnil(L, -1)) 01021 return 1; 01022 01023 lua_settop(L, 2); /* reset stack */ 01024 Property_get(L); /* pushes property var */ 01025 lua_replace(L, 1); /* replace prop with var */ 01026 return Variable_index(L); 01027 } 01028 01029 static int Property_newindex(lua_State *L) 01030 { 01031 Property_get(L); 01032 lua_replace(L, 1); 01033 return Variable_newindex(L); 01034 } 01035 01036 static const struct luaL_Reg Property_f [] = { 01037 {"new", Property_new }, 01038 {"get", Property_get }, 01039 {"getRaw", Property_getRaw }, 01040 {"set", Property_set }, 01041 {"info", Property_info }, 01042 {"delete", Property_del }, 01043 {NULL, NULL} 01044 }; 01045 01046 static const struct luaL_Reg Property_m [] = { 01047 {"get", Property_get }, 01048 {"getRaw", Property_getRaw }, 01049 {"set", Property_set }, 01050 {"info", Property_info }, 01051 // todo: shall we or not? s.o. {"__gc", Property_gc }, 01052 {"delete", Property_del }, 01053 {"__index", Property_index }, 01054 {"__newindex", Property_newindex }, 01055 {NULL, NULL} 01056 }; 01057 01058 /*************************************************************** 01059 * Ports (boxed) 01060 ***************************************************************/ 01061 01062 /* both input or output */ 01063 static int Port_info(lua_State *L) 01064 { 01065 int arg_type; 01066 const char* port_type = NULL; 01067 PortInterface **pip; 01068 PortInterface *pi = NULL; 01069 01070 if((pip = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) { 01071 pi = *pip; 01072 port_type = "in"; 01073 } else if((pip = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) { 01074 pi = *pip; 01075 port_type = "out"; 01076 } 01077 else { 01078 arg_type = lua_type(L, 1); 01079 luaL_error(L, "Port.info: invalid argument, expected Port, got %s", 01080 lua_typename(L, arg_type)); 01081 } 01082 01083 lua_newtable(L); 01084 lua_pushstring(L, "name"); lua_pushstring(L, pi->getName().c_str()); lua_rawset(L, -3); 01085 lua_pushstring(L, "desc"); lua_pushstring(L, pi->getDescription().c_str()); lua_rawset(L, -3); 01086 lua_pushstring(L, "connected"); lua_pushboolean(L, pi->connected()); lua_rawset(L, -3); 01087 lua_pushstring(L, "isLocal"); lua_pushboolean(L, pi->isLocal()); lua_rawset(L, -3); 01088 lua_pushstring(L, "type"); lua_pushstring(L, pi->getTypeInfo()->getTypeName().c_str()); lua_rawset(L, -3); 01089 lua_pushstring(L, "porttype"); lua_pushstring(L, port_type); lua_rawset(L, -3); 01090 01091 return 1; 01092 } 01093 01094 static int Port_connect(lua_State *L) 01095 { 01096 int arg_type, ret; 01097 PortInterface **pip1, **pip2; 01098 PortInterface *pi1 = NULL; 01099 PortInterface *pi2 = NULL; 01100 ConnPolicy **cpp; 01101 ConnPolicy *cp = NULL; 01102 01103 if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) { 01104 pi1= *pip1; 01105 } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) { 01106 pi1= *pip1; 01107 } 01108 else { 01109 arg_type = lua_type(L, 1); 01110 luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s", 01111 lua_typename(L, arg_type)); 01112 } 01113 if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) { 01114 pi2= *pip2; 01115 } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) { 01116 pi2= *pip2; 01117 } 01118 else { 01119 arg_type = lua_type(L, 2); 01120 luaL_error(L, "Port.connect: invalid argument 2, expected Port, got %s", 01121 lua_typename(L, arg_type)); 01122 } 01123 01124 if((cpp = (ConnPolicy**) luaL_testudata(L, 3, "ConnPolicy")) != NULL) { 01125 cp=*cpp; 01126 } 01127 01128 if ( cp ) 01129 ret = pi1->connectTo(pi2, *cp); 01130 else 01131 ret = pi1->connectTo(pi2); 01132 01133 lua_pushboolean(L, ret); 01134 01135 return 1; 01136 } 01137 01138 static int Port_disconnect(lua_State *L) 01139 { 01140 int arg_type, ret; 01141 PortInterface **pip1, **pip2; 01142 PortInterface *pi1 = NULL; 01143 PortInterface *pi2 = NULL; 01144 01145 if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) { 01146 pi1= *pip1; 01147 } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) { 01148 pi1= *pip1; 01149 } 01150 else { 01151 arg_type = lua_type(L, 1); 01152 luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s", 01153 lua_typename(L, arg_type)); 01154 } 01155 if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) { 01156 pi2= *pip2; 01157 } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) { 01158 pi2= *pip2; 01159 } 01160 01161 if (pi2 != NULL) 01162 ret = pi1->disconnect(pi2); 01163 else{ 01164 pi1->disconnect(); 01165 ret = 1; 01166 } 01167 lua_pushboolean(L, ret); 01168 01169 return 1; 01170 } 01171 01172 01173 01174 /* InputPort (boxed) */ 01175 01176 gen_push_bxptr(InputPort_push, "InputPort", InputPortInterface) 01177 01178 static int InputPort_new(lua_State *L) 01179 { 01180 const char *type, *name, *desc; 01181 InputPortInterface* ipi; 01182 int argc = lua_gettop(L); 01183 01184 type = luaL_checkstring(L, 1); 01185 01186 /* name and description are optional */ 01187 name = (argc > 1) ? luaL_checkstring(L, 2) : ""; 01188 desc = (argc > 2) ? luaL_checkstring(L, 3) : ""; 01189 01190 types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type); 01191 if(ti==0) 01192 luaL_error(L, "InputPort.new: unknown type %s", type); 01193 01194 ipi = ti->inputPort(name); 01195 01196 if(!ipi) 01197 luaL_error(L, "InputPort.new: creating port of type %s failed", type); 01198 01199 ipi->doc(desc); 01200 InputPort_push(L, ipi); 01201 return 1; 01202 } 01203 01204 static int InputPort_read(lua_State *L) 01205 { 01206 int ret = 1; 01207 InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface)); 01208 DataSourceBase::shared_ptr dsb; 01209 DataSourceBase::shared_ptr *dsbp; 01210 FlowStatus fs; 01211 01212 /* if we get don't get a DS to store the result, create one */ 01213 if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) 01214 dsb = *dsbp; 01215 else { 01216 dsb = ip->getTypeInfo()->buildValue(); 01217 ret = 2; 01218 } 01219 01220 fs = ip->read(dsb); 01221 01222 if(fs == NoData) lua_pushstring(L, "NoData"); 01223 else if (fs == NewData) lua_pushstring(L, "NewData"); 01224 else if (fs == OldData) lua_pushstring(L, "OldData"); 01225 else luaL_error(L, "InputPort.read: unknown FlowStatus returned"); 01226 01227 if(ret>1) 01228 Variable_push_coerce(L, dsb); 01229 01230 return ret; 01231 } 01232 01233 #ifdef NOT_USED_YET 01234 static int InputPort_gc(lua_State *L) 01235 { 01236 InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface)); 01237 delete ip; 01238 return 0; 01239 } 01240 #endif 01241 01242 /* only explicit destruction allowed */ 01243 static int InputPort_del(lua_State *L) 01244 { 01245 InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface)); 01246 delete ip; 01247 01248 /* this prevents calling rtt methods which would cause a crash */ 01249 luaL_getmetatable(L, "__dead__"); 01250 lua_setmetatable(L, -2); 01251 return 0; 01252 } 01253 01254 static const struct luaL_Reg InputPort_f [] = { 01255 {"new", InputPort_new }, 01256 {"read", InputPort_read }, 01257 {"info", Port_info }, 01258 {"connect", Port_connect }, 01259 {"disconnect", Port_disconnect }, 01260 {"delete", InputPort_del }, 01261 {NULL, NULL} 01262 }; 01263 01264 static const struct luaL_Reg InputPort_m [] = { 01265 {"read", InputPort_read }, 01266 {"info", Port_info }, 01267 {"delete", InputPort_del }, 01268 {"connect", Port_connect }, 01269 {"disconnect", Port_disconnect }, 01270 /* {"__gc", InputPort_gc }, */ 01271 {NULL, NULL} 01272 }; 01273 01274 /* OutputPort */ 01275 01276 gen_push_bxptr(OutputPort_push, "OutputPort", OutputPortInterface) 01277 01278 01279 static int OutputPort_new(lua_State *L) 01280 { 01281 const char *type, *name, *desc; 01282 OutputPortInterface* opi; 01283 int argc = lua_gettop(L); 01284 01285 type = luaL_checkstring(L, 1); 01286 01287 /* name and description are optional */ 01288 name = (argc > 1) ? luaL_checkstring(L, 2) : ""; 01289 desc = (argc > 2) ? luaL_checkstring(L, 3) : ""; 01290 01291 types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type); 01292 01293 if(ti==0) 01294 luaL_error(L, "OutputPort.new: unknown type %s", type); 01295 01296 opi = ti->outputPort(name); 01297 01298 if(!opi) 01299 luaL_error(L, "OutputPort.new: creating port of type %s failed", type); 01300 01301 opi->doc(desc); 01302 OutputPort_push(L, opi); 01303 return 1; 01304 } 01305 01306 static int OutputPort_write(lua_State *L) 01307 { 01308 DataSourceBase::shared_ptr dsb; 01309 DataSourceBase::shared_ptr *dsbp; 01310 01311 OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface)); 01312 01313 /* fastpath: Variable argument */ 01314 if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01315 dsb = *dsbp; 01316 } else { 01317 /* slowpath: convert lua value to dsb */ 01318 dsb = Variable_fromlua(L, op->getTypeInfo(), 2); 01319 } 01320 op->write(dsb); 01321 return 0; 01322 } 01323 01324 #ifdef NOT_USED_YET 01325 static int OutputPort_gc(lua_State *L) 01326 { 01327 OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface)); 01328 delete op; 01329 return 0; 01330 } 01331 #endif 01332 01333 /* only explicit destruction allowed */ 01334 static int OutputPort_del(lua_State *L) 01335 { 01336 OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface)); 01337 delete op; 01338 01339 /* this prevents calling rtt methods which would cause a crash */ 01340 luaL_getmetatable(L, "__dead__"); 01341 lua_setmetatable(L, -2); 01342 return 0; 01343 } 01344 01345 static const struct luaL_Reg OutputPort_f [] = { 01346 {"new", OutputPort_new }, 01347 {"write", OutputPort_write }, 01348 {"info", Port_info }, 01349 {"connect", Port_connect }, 01350 {"disconnect", Port_disconnect }, 01351 {"delete", OutputPort_del }, 01352 {NULL, NULL} 01353 }; 01354 01355 static const struct luaL_Reg OutputPort_m [] = { 01356 {"write", OutputPort_write }, 01357 {"info", Port_info }, 01358 {"connect", Port_connect }, 01359 {"disconnect", Port_disconnect }, 01360 {"delete", OutputPort_del }, 01361 /* {"__gc", OutputPort_gc }, */ 01362 {NULL, NULL} 01363 }; 01364 01365 /*************************************************************** 01366 * Operation 01367 ***************************************************************/ 01368 01369 struct OperationHandle { 01370 OperationInterfacePart *oip; 01371 OperationCallerC *occ; 01372 unsigned int arity; 01373 bool is_void; 01374 01375 /* we need to store references to the dsb which we created 01376 on-the-fly, because the ReferenceDSB does not hold a 01377 shared_ptr, and hence these DSN might get destructed 01378 before/during the call 01379 */ 01380 std::vector<base::DataSourceBase::shared_ptr> dsb_store; 01381 std::vector<internal::Reference*> args; 01382 base::DataSourceBase::shared_ptr call_dsb; 01383 base::DataSourceBase::shared_ptr ret_dsb; 01384 }; 01385 01386 template<typename T> 01387 int OperationGC(lua_State* L) 01388 { 01389 T* oh = (T*) lua_touserdata(L, 1); 01390 delete oh->occ; 01391 reinterpret_cast<T*>(lua_touserdata(L, 1))->~T(); 01392 return 0; 01393 } 01394 01395 static int Operation_info(lua_State *L) 01396 { 01397 int i=1; 01398 std::vector<ArgumentDescription> args; 01399 OperationHandle *op = luaM_checkudata_mt(L, 1, "Operation", OperationHandle); 01400 01401 lua_pushstring(L, op->oip->getName().c_str()); /* name */ 01402 lua_pushstring(L, op->oip->description().c_str()); /* description */ 01403 lua_pushstring(L, op->oip->resultType().c_str()); /* result type */ 01404 lua_pushinteger(L, op->arity); /* arity */ 01405 01406 args = op->oip->getArgumentList(); 01407 01408 lua_newtable(L); 01409 01410 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) { 01411 lua_newtable(L); 01412 lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3); 01413 lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3); 01414 lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3); 01415 lua_rawseti(L, -2, i++); 01416 } 01417 return 5; 01418 } 01419 01420 static int __Operation_call(lua_State *L) 01421 { 01422 bool ret; 01423 DataSourceBase::shared_ptr dsb, *dsbp; 01424 01425 OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle); 01426 OperationInterfacePart *oip = oh->oip; 01427 unsigned int argc = lua_gettop(L); 01428 01429 if(oh->arity != argc-1) 01430 luaL_error(L, "Operation.call: wrong number of args. expected %d, got %d", oh->arity, argc-1); 01431 01432 /* update dsbs */ 01433 for(unsigned int arg=2; arg<=argc; arg++) { 01434 /* fastpath: Variable argument */ 01435 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01436 dsb = *dsbp; 01437 } else { 01438 /* slowpath: convert lua value to dsb */ 01439 dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg); 01440 /* this dsb must outlive occ->call (see comment in 01441 OperationHandle def.): */ 01442 oh->dsb_store.push_back(dsb); 01443 } 01444 if(!dsb->isAssignable()) 01445 luaL_error(L, "Operation.call: argument %d is not assignable.", arg-1); 01446 01447 ret = oh->args[arg-2]->setReference(dsb); 01448 if (!ret) 01449 luaL_error(L, "Operation_call: setReference failed, wrong type of argument?"); 01450 } 01451 01452 if(!oh->occ->call()) 01453 luaL_error(L, "Operation.call: call failed."); 01454 01455 oh->dsb_store.clear(); 01456 01457 if(!oh->is_void) 01458 Variable_push_coerce(L, oh->ret_dsb); 01459 else 01460 lua_pushnil(L); 01461 return 1; 01462 } 01463 01464 static int __Operation_send(lua_State *L) 01465 { 01466 DataSourceBase::shared_ptr dsb, *dsbp; 01467 01468 OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle); 01469 OperationInterfacePart *oip = oh->oip; 01470 unsigned int argc = lua_gettop(L); 01471 01472 if(oh->arity != argc-1) 01473 luaL_error(L, "Operation.send: wrong number of args. expected %d, got %d", oh->arity, argc-1); 01474 01475 /* update dsbs */ 01476 for(unsigned int arg=2; arg<=argc; arg++) { 01477 /* fastpath: Variable argument */ 01478 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01479 dsb = *dsbp; 01480 } else { 01481 /* slowpath: convert lua value to dsb */ 01482 dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg); 01483 /* this dsb must outlive occ->call (see comment in 01484 OperationHandle def.): */ 01485 oh->dsb_store.push_back(dsb); 01486 } 01487 oh->args[arg-2]->setReference(dsb); 01488 } 01489 01490 luaM_pushobject_mt(L, "SendHandle", SendHandleC)(oh->occ->send()); 01491 return 1; 01492 } 01493 01494 static int Operation_call(lua_State *L) 01495 { 01496 int ret; 01497 try { 01498 ret = __Operation_call(L); 01499 } catch(const std::exception &exc) { 01500 luaL_error(L, "Operation.call: caught exception '%s'", exc.what()); 01501 } catch(...) { 01502 luaL_error(L, "Operation.call: caught unknown exception"); 01503 } 01504 return ret; 01505 } 01506 01507 static int Operation_send(lua_State *L) 01508 { 01509 int ret; 01510 try { 01511 ret = __Operation_send(L); 01512 } catch(const std::exception &exc) { 01513 luaL_error(L, "Operation.send: caught exception '%s'", exc.what()); 01514 } catch(...) { 01515 luaL_error(L, "Operation.send: caught unknown exception"); 01516 } 01517 return ret; 01518 } 01519 01520 01521 static const struct luaL_Reg Operation_f [] = { 01522 { "info", Operation_info }, 01523 { "call", Operation_call }, 01524 { "send", Operation_send }, 01525 { NULL, NULL } 01526 01527 }; 01528 01529 static const struct luaL_Reg Operation_m [] = { 01530 { "info", Operation_info }, 01531 { "send", Operation_send }, 01532 { "__call", Operation_call }, 01533 { "__gc", OperationGC<OperationHandle> }, 01534 { NULL, NULL } 01535 }; 01536 01537 /*************************************************************** 01538 * Service (boxed) 01539 ***************************************************************/ 01540 01541 static int Service_getName(lua_State *L) 01542 { 01543 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01544 lua_pushstring(L, srv->getName().c_str()); 01545 return 1; 01546 } 01547 01548 static int Service_doc(lua_State *L) 01549 { 01550 int ret; 01551 const char* doc; 01552 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01553 if(lua_gettop(L) == 1) { 01554 lua_pushstring(L, srv->doc().c_str()); 01555 ret = 1; 01556 } else { 01557 doc = luaL_checkstring(L, 2); 01558 srv->doc(doc); 01559 ret = 0; 01560 } 01561 01562 return ret; 01563 } 01564 01565 static int Service_getProviderNames(lua_State *L) 01566 { 01567 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01568 push_vect_str(L, srv->getProviderNames()); 01569 return 1; 01570 } 01571 01572 static int Service_getOperationNames(lua_State *L) 01573 { 01574 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01575 push_vect_str(L, srv->getOperationNames()); 01576 return 1; 01577 } 01578 01579 01580 static int Service_hasOperation(lua_State *L) 01581 { 01582 int ret; 01583 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01584 const char* op = luaL_checkstring(L, 2); 01585 ret = srv->hasOperation(op); 01586 lua_pushboolean(L, ret); 01587 return 1; 01588 } 01589 01590 static int Service_getPortNames(lua_State *L) 01591 { 01592 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01593 push_vect_str(L, srv->getPortNames()); 01594 return 1; 01595 } 01596 01597 static int Service_provides(lua_State *L) 01598 { 01599 int ret, i, argc; 01600 const char* subsrv_str; 01601 Service::shared_ptr srv, subsrv; 01602 01603 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01604 argc=lua_gettop(L); 01605 01606 /* return "this" if no args given */ 01607 if(argc == 1) { 01608 ret = 1; 01609 goto out; 01610 } 01611 01612 for(i=2; i<=argc; i++) { 01613 subsrv_str = luaL_checkstring(L, i); 01614 // subsrv = srv->provides(subsrv_str); 01615 subsrv = srv->getService(subsrv_str); 01616 if (subsrv == 0) 01617 luaL_error(L, "Service.provides: no subservice %s of service %s", 01618 srv->getName().c_str(), subsrv_str); 01619 else 01620 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(subsrv); 01621 } 01622 ret = argc - 1; 01623 01624 out: 01625 return ret; 01626 } 01627 01628 static int Service_getOperation(lua_State *L) 01629 { 01630 const char *op_str; 01631 OperationInterfacePart *oip; 01632 Service::shared_ptr srv; 01633 DataSourceBase::shared_ptr dsb; 01634 const types::TypeInfo *ti; 01635 OperationHandle *oh; 01636 TaskContext *this_tc; 01637 01638 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01639 op_str = luaL_checkstring(L, 2); 01640 oip = srv->getOperation(op_str); 01641 01642 if(!oip) 01643 luaL_error(L, "Service_getOperation: service %s has no operation %s", 01644 srv->getName().c_str(), op_str); 01645 01646 oh = (OperationHandle*) luaM_pushobject_mt(L, "Operation", OperationHandle)(); 01647 oh->oip = oip; 01648 oh->arity = oip->arity(); 01649 oh->args.reserve(oh->arity); 01650 this_tc = __getTC(L); 01651 01652 oh->occ = new OperationCallerC(oip, op_str, this_tc->engine()); 01653 01654 /* create args 01655 * getArgumentType(0) is return value 01656 */ 01657 for(unsigned int arg=1; arg <= oh->arity; arg++) { 01658 std::string type = oip->getArgumentType(arg)->getTypeName(); 01659 ti = types::TypeInfoRepository::Instance()->type(type); 01660 if(!ti) 01661 luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for arg %d of type '%s'", 01662 op_str, arg, type.c_str()); 01663 01664 dsb = ti->buildReference((void*) 0xdeadbeef); 01665 if(!dsb) 01666 luaL_error(L, "Operation.call: '%s', failed to build DSB for arg %d of type '%s'", 01667 op_str, arg, type.c_str()); 01668 01669 oh->args.push_back(dynamic_cast<internal::Reference*>(dsb.get())); 01670 oh->occ->arg(dsb); 01671 } 01672 01673 /* return value */ 01674 if(oip->resultType() != "void"){ 01675 ti = oip->getArgumentType(0); // 0 == return type 01676 if(!ti) 01677 luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for return value of type '%s'", 01678 op_str, oip->resultType().c_str()); 01679 oh->ret_dsb=ti->buildValue(); 01680 if(!oh->ret_dsb) 01681 luaL_error(L, "Operation.call: '%s', failed to build DSB for return value of type '%s'", 01682 op_str, oip->resultType().c_str()); 01683 01684 oh->occ->ret(oh->ret_dsb); 01685 oh->is_void=false; 01686 } else { 01687 oh->is_void=true; 01688 } 01689 01690 if(!oh->occ->ready()) 01691 luaL_error(L, "Service.getOperation: OperationCallerC not ready!"); 01692 01693 return 1; 01694 } 01695 01696 static int Service_getPort(lua_State *L) 01697 { 01698 const char* name; 01699 PortInterface *pi; 01700 InputPortInterface *ipi; 01701 OutputPortInterface *opi; 01702 01703 Service::shared_ptr srv; 01704 01705 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01706 name = luaL_checkstring(L, 2); 01707 01708 pi = srv->getPort(name); 01709 if(!pi) 01710 luaL_error(L, "Service.getPort: service %s has no port %", 01711 srv->getName().c_str(), name); 01712 01713 /* input or output? */ 01714 if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL) 01715 InputPort_push(L, ipi); 01716 else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL) 01717 OutputPort_push(L, opi); 01718 else 01719 luaL_error(L, "Service.getPort: unknown port type returned"); 01720 01721 return 1; 01722 } 01723 01724 static int Service_getProperty(lua_State *L) 01725 { 01726 const char *name; 01727 PropertyBase *prop; 01728 01729 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01730 name = luaL_checkstring(L, 2); 01731 01732 prop = srv->getProperty(name); 01733 01734 if(!prop) 01735 luaL_error(L, "%s failed. No such property", __FILE__); 01736 01737 Property_push(L, prop); 01738 return 1; 01739 } 01740 01741 static int Service_getPropertyNames(lua_State *L) 01742 { 01743 Service::shared_ptr srv; 01744 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01745 std::vector<std::string> plist = srv->properties()->list(); 01746 push_vect_str(L, plist); 01747 return 1; 01748 } 01749 01750 static int Service_getProperties(lua_State *L) 01751 { 01752 Service::shared_ptr srv; 01753 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01754 vector<PropertyBase*> props = srv->properties()->getProperties(); 01755 01756 int key = 1; 01757 lua_createtable(L, props.size(), 0); 01758 for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) { 01759 Property_push(L, *it); 01760 lua_rawseti(L, -2, key++); 01761 } 01762 01763 return 1; 01764 } 01765 01766 static const struct luaL_Reg Service_f [] = { 01767 { "getName", Service_getName }, 01768 { "doc", Service_doc }, 01769 { "getProviderNames", Service_getProviderNames }, 01770 { "getOperationNames", Service_getOperationNames }, 01771 { "hasOperation", Service_hasOperation }, 01772 { "getPortNames", Service_getPortNames }, 01773 { "provides", Service_provides }, 01774 { "getOperation", Service_getOperation }, 01775 { "getPort", Service_getPort }, 01776 { "getProperty", Service_getProperty }, 01777 { "getProperties", Service_getProperties }, 01778 { "getPropertyNames", Service_getPropertyNames }, 01779 { NULL, NULL } 01780 }; 01781 01782 static const struct luaL_Reg Service_m [] = { 01783 { "getName", Service_getName }, 01784 { "doc", Service_doc }, 01785 { "getProviderNames", Service_getProviderNames }, 01786 { "getOperationNames", Service_getOperationNames }, 01787 { "hasOperation", Service_hasOperation }, 01788 { "getPortNames", Service_getPortNames }, 01789 { "provides", Service_provides }, 01790 { "getOperation", Service_getOperation }, 01791 { "getPort", Service_getPort }, 01792 { "getProperty", Service_getProperty }, 01793 { "getProperties", Service_getProperties }, 01794 { "getPropertyNames", Service_getPropertyNames }, 01795 { "__gc", GCMethod<Service::shared_ptr> }, 01796 { NULL, NULL } 01797 }; 01798 01799 /*************************************************************** 01800 * ServiceRequester 01801 ***************************************************************/ 01802 01803 gen_push_bxptr(ServiceRequester_push, "ServiceRequester", ServiceRequester) 01804 01805 static int ServiceRequester_getRequestName(lua_State *L) 01806 { 01807 ServiceRequester *sr; 01808 01809 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 01810 lua_pushstring(L, sr->getRequestName().c_str()); 01811 return 1; 01812 } 01813 01814 static int ServiceRequester_getRequesterNames(lua_State *L) 01815 { 01816 ServiceRequester *sr; 01817 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 01818 push_vect_str(L, sr->getRequesterNames()); 01819 return 1; 01820 } 01821 01822 static int ServiceRequester_ready(lua_State *L) 01823 { 01824 int ret; 01825 ServiceRequester *sr; 01826 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 01827 ret = sr->ready(); 01828 lua_pushboolean(L, ret); 01829 return 1; 01830 } 01831 01832 static int ServiceRequester_disconnect(lua_State *L) 01833 { 01834 ServiceRequester *sr; 01835 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 01836 sr->disconnect(); 01837 return 0; 01838 } 01839 01840 static int ServiceRequester_requires(lua_State *L) 01841 { 01842 int argc, ret, i; 01843 const char* subsr_str; 01844 ServiceRequester *sr; 01845 ServiceRequester *subsr; 01846 01847 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 01848 argc = lua_gettop(L); 01849 01850 /* return "this" if no args given */ 01851 if(argc == 1) { 01852 ret = 1; 01853 goto out; 01854 } 01855 01856 for(i=2; i<=argc; i++) { 01857 subsr_str = luaL_checkstring(L, i); 01858 subsr = sr->requires(subsr_str); 01859 if (subsr == 0) 01860 luaL_error(L, "ServiceRequester: no required subservice %s of service %s", 01861 subsr_str, sr->getRequestName().c_str()); 01862 else 01863 ServiceRequester_push(L, subsr); 01864 } 01865 ret = argc - 1; 01866 01867 out: 01868 return ret; 01869 } 01870 01871 static const struct luaL_Reg ServiceRequester_f [] = { 01872 { "getRequestName", ServiceRequester_getRequestName }, 01873 { "getRequesterNames", ServiceRequester_getRequesterNames }, 01874 { "ready", ServiceRequester_ready }, 01875 { "disconnect", ServiceRequester_disconnect }, 01876 { "requires", ServiceRequester_requires }, 01877 { NULL, NULL } 01878 }; 01879 01880 static const struct luaL_Reg ServiceRequester_m [] = { 01881 { "getRequestName", ServiceRequester_getRequestName }, 01882 { "getRequesterNames", ServiceRequester_getRequesterNames }, 01883 { "ready", ServiceRequester_ready }, 01884 { "disconnect", ServiceRequester_disconnect }, 01885 { "requires", ServiceRequester_requires }, 01886 { NULL, NULL } 01887 }; 01888 01889 01890 /*************************************************************** 01891 * TaskContext (boxed) 01892 ***************************************************************/ 01893 01894 gen_push_bxptr(TaskContext_push, "TaskContext", TaskContext) 01895 01896 static int TaskContext_getName(lua_State *L) 01897 { 01898 const char *s; 01899 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01900 s = tc->getName().c_str(); 01901 lua_pushstring(L, s); 01902 return 1; 01903 } 01904 01905 static int TaskContext_start(lua_State *L) 01906 { 01907 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01908 bool b = tc->start(); 01909 lua_pushboolean(L, b); 01910 return 1; 01911 } 01912 01913 static int TaskContext_stop(lua_State *L) 01914 { 01915 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01916 bool b = tc->stop(); 01917 lua_pushboolean(L, b); 01918 return 1; 01919 } 01920 01921 static int TaskContext_configure(lua_State *L) 01922 { 01923 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01924 bool ret = tc->configure(); 01925 lua_pushboolean(L, ret); 01926 return 1; 01927 } 01928 01929 static int TaskContext_activate(lua_State *L) 01930 { 01931 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01932 bool ret = tc->activate(); 01933 lua_pushboolean(L, ret); 01934 return 1; 01935 } 01936 01937 static int TaskContext_cleanup(lua_State *L) 01938 { 01939 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01940 bool ret = tc->cleanup(); 01941 lua_pushboolean(L, ret); 01942 return 1; 01943 } 01944 01945 static int TaskContext_error(lua_State *L) 01946 { 01947 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01948 tc->error(); 01949 return 0; 01950 } 01951 01952 static int TaskContext_recover(lua_State *L) 01953 { 01954 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01955 bool ret = tc->recover(); 01956 lua_pushboolean(L, ret); 01957 return 1; 01958 } 01959 01960 static int TaskContext_getState(lua_State *L) 01961 { 01962 TaskCore::TaskState ts; 01963 TaskContext **tc = (TaskContext**) luaM_checkudata_bx(L, 1, TaskContext); 01964 ts = (*tc)->getTaskState(); 01965 01966 switch(ts) { 01967 case TaskCore::Init: lua_pushstring(L, "Init"); break; 01968 case TaskCore::PreOperational: lua_pushstring(L, "PreOperational"); break; 01969 case TaskCore::FatalError: lua_pushstring(L, "FatalError"); break; 01970 case TaskCore::Exception: lua_pushstring(L, "Exception"); break; 01971 case TaskCore::Stopped: lua_pushstring(L, "Stopped"); break; 01972 case TaskCore::Running: lua_pushstring(L, "Running"); break; 01973 case TaskCore::RunTimeError: lua_pushstring(L, "RunTimeError"); break; 01974 default: lua_pushstring(L, "unknown"); 01975 } 01976 return 1; 01977 } 01978 01979 /* string-table getPeers(TaskContext self)*/ 01980 /* should better return array of TC's */ 01981 static int TaskContext_getPeers(lua_State *L) 01982 { 01983 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 01984 std::vector<std::string> plist = tc->getPeerList(); 01985 push_vect_str(L, plist); 01986 return 1; 01987 } 01988 01989 /* bool addPeer(TaskContext self, TaskContext peer)*/ 01990 static int TaskContext_addPeer(lua_State *L) 01991 { 01992 bool ret; 01993 TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext)); 01994 TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext)); 01995 ret = self->addPeer(peer); 01996 lua_pushboolean(L, ret); 01997 return 1; 01998 } 01999 02000 /* void removePeer(TaskContext self, string peer)*/ 02001 static int TaskContext_removePeer(lua_State *L) 02002 { 02003 std::string peer; 02004 TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext)); 02005 peer = luaL_checkstring(L, 2); 02006 self->removePeer(peer); 02007 return 0; 02008 } 02009 02010 /* TaskContext getPeer(string name) */ 02011 static int TaskContext_getPeer(lua_State *L) 02012 { 02013 std::string strpeer; 02014 TaskContext *peer; 02015 TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext)); 02016 strpeer = luaL_checkstring(L, 2); 02017 peer = self->getPeer(strpeer); 02018 02019 if(!peer) { 02020 luaL_error(L, "TaskContext.getPeer: no peer %s", strpeer.c_str()); 02021 goto out; 02022 } 02023 02024 TaskContext_push(L, peer); 02025 out: 02026 return 1; 02027 } 02028 02029 static int TaskContext_getPortNames(lua_State *L) 02030 { 02031 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02032 std::vector<std::string> plist = tc->ports()->getPortNames(); 02033 push_vect_str(L, plist); 02034 return 1; 02035 } 02036 02037 static int TaskContext_addPort(lua_State *L) 02038 { 02039 const char* name, *desc; 02040 PortInterface **pi; 02041 int argc = lua_gettop(L); 02042 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02043 02044 pi = (PortInterface**) luaL_testudata(L, 2, "InputPort"); 02045 if(pi) goto check_name; 02046 02047 pi = (PortInterface**) luaL_testudata(L, 2, "OutputPort"); 02048 if(pi) goto check_name; 02049 02050 return luaL_error(L, "addPort: invalid argument, not a Port"); 02051 02052 check_name: 02053 if(argc > 2) { 02054 name = luaL_checkstring(L, 3); 02055 (*pi)->setName(name); 02056 } 02057 02058 if(argc > 3) { 02059 desc = luaL_checkstring(L, 4); 02060 (*pi)->doc(desc); 02061 } 02062 02063 tc->ports()->addPort(**pi); 02064 return 0; 02065 } 02066 02067 static int TaskContext_addEventPort(lua_State *L) 02068 { 02069 const char* name, *desc; 02070 InputPortInterface **ipi; 02071 int argc = lua_gettop(L); 02072 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02073 02074 if((ipi = (InputPortInterface**) luaL_testudata(L, 2, "InputPort")) == NULL) 02075 return luaL_error(L, "addEventPort: invalid argument, not an InputPort"); 02076 02077 if(argc > 2) { 02078 name = luaL_checkstring(L, 3); 02079 (*ipi)->setName(name); 02080 } 02081 02082 if(argc > 3) { 02083 desc = luaL_checkstring(L, 4); 02084 (*ipi)->doc(desc); 02085 } 02086 02087 tc->ports()->addEventPort(**ipi); 02088 return 0; 02089 } 02090 02091 static int TaskContext_getPort(lua_State *L) 02092 { 02093 const char* name; 02094 PortInterface *pi; 02095 InputPortInterface *ipi; 02096 OutputPortInterface *opi; 02097 02098 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02099 name = luaL_checkstring(L, 2); 02100 02101 pi = tc->getPort(name); 02102 if(!pi) 02103 luaL_error(L, "TaskContext.getPort: no port %s for taskcontext %s", 02104 name, tc->getName().c_str()); 02105 02106 /* input or output? */ 02107 if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL) 02108 InputPort_push(L, ipi); 02109 else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL) 02110 OutputPort_push(L, opi); 02111 else 02112 luaL_error(L, "TaskContext.getPort: unknown port returned"); 02113 02114 return 1; 02115 } 02116 02117 static int TaskContext_removePort(lua_State *L) 02118 { 02119 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02120 const char *port = luaL_checkstring(L, 2); 02121 tc->ports()->removePort(port); 02122 return 0; 02123 } 02124 02125 static int TaskContext_addProperty(lua_State *L) 02126 { 02127 const char *name, *desc; 02128 int argc = lua_gettop(L); 02129 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02130 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Property", PropertyBase)); 02131 02132 if(argc > 2) { 02133 name = luaL_checkstring(L, 3); 02134 pb->setName(name); 02135 } 02136 02137 if(argc > 3) { 02138 desc = luaL_checkstring(L, 4); 02139 pb->setDescription(desc); 02140 } 02141 02142 02143 if(!tc->addProperty(*pb)) 02144 luaL_error(L, "TaskContext.addProperty: failed to add property %s.", 02145 pb->getName().c_str()); 02146 02147 return 0; 02148 } 02149 02150 static int TaskContext_getProperty(lua_State *L) 02151 { 02152 const char *name; 02153 PropertyBase *prop; 02154 02155 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02156 name = luaL_checkstring(L, 2); 02157 02158 prop = tc->getProperty(name); 02159 02160 if(!prop) 02161 luaL_error(L, "%s failed. No such property", __FILE__); 02162 02163 Property_push(L, prop); 02164 return 1; 02165 } 02166 02167 02168 static int TaskContext_getPropertyNames(lua_State *L) 02169 { 02170 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02171 std::vector<std::string> plist = tc->properties()->list(); 02172 push_vect_str(L, plist); 02173 return 1; 02174 } 02175 02176 static int TaskContext_getProperties(lua_State *L) 02177 { 02178 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02179 vector<PropertyBase*> props = tc->properties()->getProperties(); 02180 02181 int key = 1; 02182 lua_createtable(L, props.size(), 0); 02183 for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) { 02184 Property_push(L, *it); 02185 lua_rawseti(L, -2, key++); 02186 } 02187 02188 return 1; 02189 } 02190 02191 static int TaskContext_removeProperty(lua_State *L) 02192 { 02193 const char *name; 02194 PropertyBase *prop; 02195 02196 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02197 name = luaL_checkstring(L, 2); 02198 02199 prop = tc->getProperty(name); 02200 02201 if(!prop) 02202 luaL_error(L, "%s failed. No such property", __FILE__); 02203 02204 tc->properties()->remove(prop); 02205 return 0; 02206 } 02207 02208 02209 static int TaskContext_getOps(lua_State *L) 02210 { 02211 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02212 std::vector<std::string> oplst = tc->operations()->getNames(); 02213 push_vect_str(L, oplst); 02214 return 1; 02215 } 02216 02217 /* returns restype, arity, table-of-arg-descr */ 02218 static int TaskContext_getOpInfo(lua_State *L) 02219 { 02220 int i=1; 02221 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02222 const char *op = luaL_checkstring(L, 2); 02223 std::vector<ArgumentDescription> args; 02224 02225 if(!tc->operations()->hasMember(op)) 02226 luaL_error(L, "TaskContext.getOpInfo failed: no such operation"); 02227 02228 lua_pushstring(L, tc->operations()->getResultType(op).c_str()); /* result type */ 02229 lua_pushinteger(L, tc->operations()->getArity(op)); /* arity */ 02230 lua_pushstring(L, tc->operations()->getDescription(op).c_str()); /* description */ 02231 02232 args = tc->operations()->getArgumentList(op); 02233 02234 lua_newtable(L); 02235 02236 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) { 02237 lua_newtable(L); 02238 lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3); 02239 lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3); 02240 lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3); 02241 lua_rawseti(L, -2, i++); 02242 } 02243 02244 return 4; 02245 } 02246 02247 static int TaskContext_provides(lua_State *L) 02248 { 02249 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02250 Service::shared_ptr srv = tc->provides(); 02251 02252 if(srv == 0) 02253 luaL_error(L, "TaskContext.provides: no default service"); 02254 02255 /* forward to Serivce.provides */ 02256 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv); 02257 lua_replace(L, 1); 02258 return Service_provides(L); 02259 } 02260 02261 static int TaskContext_getProviderNames(lua_State *L) 02262 { 02263 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02264 Service::shared_ptr srv = tc->provides(); 02265 push_vect_str(L, srv->getProviderNames()); 02266 return 1; 02267 } 02268 02269 static int TaskContext_requires(lua_State *L) 02270 { 02271 ServiceRequester *sr; 02272 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02273 sr = tc->requires(); 02274 02275 if(!sr) 02276 luaL_error(L, "TaskContext.requires returned NULL"); 02277 02278 ServiceRequester_push(L, sr); 02279 lua_replace(L, 1); 02280 return ServiceRequester_requires(L); 02281 } 02282 02283 static int TaskContext_connectServices(lua_State *L) 02284 { 02285 int ret; 02286 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02287 TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext)); 02288 ret = tc->connectServices(peer); 02289 lua_pushboolean(L, ret); 02290 return 1; 02291 } 02292 02293 static int TaskContext_hasOperation(lua_State *L) 02294 { 02295 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02296 Service::shared_ptr srv = tc->provides(); 02297 02298 if(srv == 0) 02299 luaL_error(L, "TaskContext.provides: no default service"); 02300 02301 /* forward to Serivce.hasOperation */ 02302 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv); 02303 lua_replace(L, 1); 02304 return Service_hasOperation(L); 02305 } 02306 02307 02308 static int TaskContext_getOperation(lua_State *L) 02309 { 02310 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02311 Service::shared_ptr srv = tc->provides(); 02312 02313 if(srv == 0) 02314 luaL_error(L, "TaskContext.getOperation: no default service"); 02315 02316 /* forward to Serivce.getOperation */ 02317 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv); 02318 lua_replace(L, 1); 02319 return Service_getOperation(L); 02320 } 02321 02322 /* 02323 * SendHandle (required for send) 02324 */ 02325 02326 static void SendStatus_push(lua_State *L, SendStatus ss) 02327 { 02328 switch (ss) { 02329 case SendSuccess: lua_pushstring(L, "SendSuccess"); break; 02330 case SendNotReady: lua_pushstring(L, "SendNotReady"); break; 02331 case SendFailure: lua_pushstring(L, "SendFailure"); break; 02332 default: lua_pushstring(L, "unkown"); 02333 } 02334 } 02335 02336 static int __SendHandle_collect(lua_State *L, bool block) 02337 { 02338 unsigned int coll_argc; 02339 std::vector<DataSourceBase::shared_ptr> coll_args; /* temporarily store args */ 02340 SendStatus ss; 02341 const types::TypeInfo *ti; 02342 OperationInterfacePart *oip; 02343 DataSourceBase::shared_ptr dsb, *dsbp; 02344 02345 unsigned int argc = lua_gettop(L); 02346 SendHandleC *shc = luaM_checkudata_mt(L, 1, "SendHandle", SendHandleC); 02347 02348 /* get orp pointer */ 02349 oip = shc->getOrp(); 02350 coll_argc = oip->collectArity(); 02351 02352 if(argc == 1) { 02353 // No args supplied, create them. 02354 for(unsigned int i=1; i<=coll_argc; i++) { 02355 ti = oip->getCollectType(i); 02356 dsb = ti->buildValue(); 02357 coll_args.push_back(dsb); 02358 shc->arg(dsb); 02359 } 02360 } else if (argc-1 == coll_argc) { 02361 // args supplied, use them. 02362 for(unsigned int arg=2; arg<=argc; arg++) { 02363 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) 02364 dsb = *dsbp; 02365 else 02366 luaL_error(L, "SendHandle.collect: expected Variable argument at position %d", arg-1); 02367 shc->arg(dsb); 02368 } 02369 } else { 02370 luaL_error(L, "SendHandle.collect: wrong number of args. expected either 0 or %d, got %d", 02371 coll_argc, argc-1); 02372 } 02373 02374 if(block) ss = shc->collect(); 02375 else ss = shc->collectIfDone(); 02376 02377 SendStatus_push(L, ss); 02378 02379 if(ss == SendSuccess) { 02380 for (unsigned int i=0; i<coll_args.size(); i++) 02381 Variable_push_coerce(L, coll_args[i]); 02382 } 02383 /* SendStatus + collect args */ 02384 return coll_args.size() + 1; 02385 } 02386 02387 static int SendHandle_collect(lua_State *L) { return __SendHandle_collect(L, true); } 02388 static int SendHandle_collectIfDone(lua_State *L) { return __SendHandle_collect(L, false); } 02389 02390 static const struct luaL_Reg SendHandle_f [] = { 02391 { "collect", SendHandle_collect }, 02392 { "collectIfDone", SendHandle_collectIfDone }, 02393 { NULL, NULL } 02394 }; 02395 02396 static const struct luaL_Reg SendHandle_m [] = { 02397 { "collect", SendHandle_collect }, 02398 { "collectIfDone", SendHandle_collectIfDone }, 02399 { "__gc", GCMethod<SendHandleC> }, 02400 { NULL, NULL } 02401 }; 02402 02403 /* only explicit destruction allowed */ 02404 static int TaskContext_del(lua_State *L) 02405 { 02406 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02407 delete tc; 02408 02409 /* this prevents calling rtt methods which would cause a crash */ 02410 luaL_getmetatable(L, "__dead__"); 02411 lua_setmetatable(L, -2); 02412 return 0; 02413 } 02414 02415 static const struct luaL_Reg TaskContext_f [] = { 02416 { "getName", TaskContext_getName }, 02417 { "start", TaskContext_start }, 02418 { "stop", TaskContext_stop }, 02419 { "configure", TaskContext_configure }, 02420 { "activate", TaskContext_activate }, 02421 { "cleanup", TaskContext_cleanup }, 02422 { "error", TaskContext_error }, 02423 { "recover", TaskContext_recover }, 02424 { "getState", TaskContext_getState }, 02425 { "getPeers", TaskContext_getPeers }, 02426 { "addPeer", TaskContext_addPeer }, 02427 { "removePeer", TaskContext_removePeer }, 02428 { "getPeer", TaskContext_getPeer }, 02429 { "getPortNames", TaskContext_getPortNames }, 02430 { "addPort", TaskContext_addPort }, 02431 { "addEventPort", TaskContext_addEventPort }, 02432 { "getPort", TaskContext_getPort }, 02433 { "removePort", TaskContext_removePort }, 02434 { "addProperty", TaskContext_addProperty }, 02435 { "getProperty", TaskContext_getProperty }, 02436 { "getProperties", TaskContext_getProperties }, 02437 { "getPropertyNames", TaskContext_getPropertyNames }, 02438 { "removeProperty", TaskContext_removeProperty }, 02439 { "getOps", TaskContext_getOps }, 02440 { "getOpInfo", TaskContext_getOpInfo }, 02441 { "hasOperation", TaskContext_hasOperation }, 02442 { "provides", TaskContext_provides }, 02443 { "getProviderNames", TaskContext_getProviderNames }, 02444 { "connectServices", TaskContext_connectServices }, 02445 { "getOperation", TaskContext_getOperation }, 02446 { "delete", TaskContext_del }, 02447 { NULL, NULL} 02448 }; 02449 02450 static const struct luaL_Reg TaskContext_m [] = { 02451 { "getName", TaskContext_getName }, 02452 { "start", TaskContext_start }, 02453 { "stop", TaskContext_stop }, 02454 { "configure", TaskContext_configure }, 02455 { "activate", TaskContext_activate }, 02456 { "cleanup", TaskContext_cleanup }, 02457 { "error", TaskContext_error }, 02458 { "recover", TaskContext_recover }, 02459 { "getState", TaskContext_getState }, 02460 { "getPeers", TaskContext_getPeers }, 02461 { "addPeer", TaskContext_addPeer }, 02462 { "removePeer", TaskContext_removePeer }, 02463 { "getPeer", TaskContext_getPeer }, 02464 { "getPortNames", TaskContext_getPortNames }, 02465 { "addPort", TaskContext_addPort }, 02466 { "addEventPort", TaskContext_addEventPort }, 02467 { "getPort", TaskContext_getPort }, 02468 { "removePort", TaskContext_removePort }, 02469 { "addProperty", TaskContext_addProperty }, 02470 { "getProperty", TaskContext_getProperty }, 02471 { "getProperties", TaskContext_getProperties }, 02472 { "getPropertyNames", TaskContext_getPropertyNames }, 02473 { "removeProperty", TaskContext_removeProperty }, 02474 { "getOps", TaskContext_getOps }, 02475 { "getOpInfo", TaskContext_getOpInfo }, 02476 { "hasOperation", TaskContext_hasOperation }, 02477 { "provides", TaskContext_provides }, 02478 { "getProviderNames", TaskContext_getProviderNames }, 02479 { "requires", TaskContext_requires }, 02480 { "connectServices", TaskContext_connectServices }, 02481 { "getOperation", TaskContext_getOperation }, 02482 { "delete", TaskContext_del }, 02483 // { "__index", TaskContext_index }, 02484 /* we don't GC TaskContexts 02485 * { "__gc", GCMethod<TaskContext> }, */ 02486 { NULL, NULL} 02487 }; 02488 02489 /* 02490 * Execution engine hook registration 02491 */ 02492 02493 /* executable IF */ 02494 class EEHook : public base::ExecutableInterface 02495 { 02496 protected: 02497 std::string func; 02498 lua_State *L; 02499 TaskContext *tc; /* remember this to be able to print TC name 02500 in error messages */ 02501 public: 02502 EEHook(lua_State *_L, std::string _func) { L = _L; func = _func; tc = __getTC(L); } 02503 bool execute() { return call_func(L, func.c_str(), tc, 1, 1); } 02504 }; 02505 02506 static int EEHook_new(lua_State *L) 02507 { 02508 const char *func; 02509 func = luaL_checkstring(L, 1); 02510 luaM_pushobject(L, EEHook)(L, func); 02511 return 1; 02512 } 02513 02514 static int EEHook_enable(lua_State *L) 02515 { 02516 EEHook *eeh = luaM_checkudata(L, 1, EEHook); 02517 TaskContext *tc = __getTC(L); 02518 lua_pushboolean(L, tc->engine()->runFunction(eeh)); 02519 return 1; 02520 } 02521 02522 static int EEHook_disable(lua_State *L) 02523 { EEHook *eeh = luaM_checkudata(L, 1, EEHook); 02524 TaskContext *tc = __getTC(L); 02525 lua_pushboolean(L, tc->engine()->removeFunction(eeh)); 02526 return 1; 02527 } 02528 02529 #if 0 02530 static int EEHook_gc(lua_State *L) 02531 { 02532 EEHook_disable(L); 02533 lua_settop(L, 1); 02534 reinterpret_cast<EEHook*>(lua_touserdata(L, 1))->~EEHook(); 02535 return 0; 02536 } 02537 #endif 02538 02539 static const struct luaL_Reg EEHook_f [] = { 02540 { "new", EEHook_new }, 02541 { "enable", EEHook_enable }, 02542 { "disable", EEHook_disable }, 02543 }; 02544 02545 02546 static const struct luaL_Reg EEHook_m [] = { 02547 { "enable", EEHook_enable }, 02548 { "disable", EEHook_disable }, 02549 /* { "__gc", EEHook_gc }, */ 02550 }; 02551 02552 02553 /* 02554 * Logger and miscellaneous 02555 */ 02556 static const char *const loglevels[] = { 02557 "Never", "Fatal", "Critical", "Error", "Warning", "Info", "Debug", "RealTime", NULL 02558 }; 02559 02560 static int Logger_setLogLevel(lua_State *L) 02561 { 02562 Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels); 02563 log().setLogLevel(ll); 02564 return 0; 02565 } 02566 02567 static int Logger_getLogLevel(lua_State *L) 02568 { 02569 Logger::LogLevel ll = log().getLogLevel(); 02570 02571 switch(ll) { 02572 case Logger::Never: lua_pushstring(L, "Never"); break; 02573 case Logger::Fatal: lua_pushstring(L, "Fatal"); break; 02574 case Logger::Critical: lua_pushstring(L, "Critical"); break; 02575 case Logger::Error: lua_pushstring(L, "Error"); break; 02576 case Logger::Warning: lua_pushstring(L, "Warning"); break; 02577 case Logger::Info: lua_pushstring(L, "Info"); break; 02578 case Logger::Debug: lua_pushstring(L, "Debug"); break; 02579 case Logger::RealTime: lua_pushstring(L, "RealTime"); break; 02580 default: 02581 lua_pushstring(L, "unknown"); 02582 } 02583 return 1; 02584 } 02585 02586 static int Logger_log(lua_State *L) 02587 { 02588 const char *mes; 02589 for(int i=1; i<=lua_gettop(L); i++) { 02590 mes = luaL_checkstring(L, i); 02591 Logger::log() << mes; 02592 } 02593 Logger::log() << endlog(); 02594 return 0; 02595 } 02596 02597 static int Logger_logl(lua_State *L) 02598 { 02599 const char *mes; 02600 Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels); 02601 for(int i=2; i<=lua_gettop(L); i++) { 02602 mes = luaL_checkstring(L, i); 02603 Logger::log(ll) << mes; 02604 } 02605 Logger::log(ll) << endlog(); 02606 return 0; 02607 } 02608 02609 /* misc stuff */ 02610 02611 static int getTime(lua_State *L) 02612 { 02613 unsigned long nsec, sec; 02614 RTT::os::TimeService::nsecs total_nsec = TimeService::Instance()->getNSecs(); 02615 sec = total_nsec / 1000000000; 02616 nsec = total_nsec % 1000000000; 02617 lua_pushinteger(L, sec); 02618 lua_pushinteger(L, nsec); 02619 return 2; 02620 } 02621 02622 static int rtt_sleep(lua_State *L) 02623 { 02624 TIME_SPEC ts; 02625 ts.tv_sec = luaL_checknumber(L, 1); 02626 ts.tv_nsec = luaL_checknumber(L, 2); 02627 rtos_nanosleep(&ts, NULL); 02628 return 0; 02629 } 02630 02631 static int getTC(lua_State *L) 02632 { 02633 lua_pushstring(L, "this_TC"); 02634 lua_rawget(L, LUA_REGISTRYINDEX); 02635 return 1; 02636 } 02637 02638 static TaskContext* __getTC(lua_State *L) 02639 { 02640 TaskContext *tc; 02641 getTC(L); 02642 tc = *(luaM_checkudata_bx(L, -1, TaskContext)); 02643 lua_pop(L, 1); 02644 return tc; 02645 } 02646 02647 /* access to the globals repository */ 02648 static int globals_getNames(lua_State *L) 02649 { 02650 GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance(); 02651 push_vect_str(L, gr->getAttributeNames() ); 02652 return 1; 02653 } 02654 02655 static int globals_get(lua_State *L) 02656 { 02657 const char *name; 02658 base::AttributeBase *ab; 02659 DataSourceBase::shared_ptr dsb; 02660 02661 name = luaL_checkstring(L, 1); 02662 GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance(); 02663 02664 ab = gr->getAttribute(name); 02665 02666 if (ab) 02667 Variable_push_coerce(L, ab->getDataSource()); 02668 else 02669 lua_pushnil(L); 02670 02671 return 1; 02672 } 02673 02674 /* global service */ 02675 static int provides_global(lua_State *L) 02676 { 02677 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(GlobalService::Instance()); 02678 lua_insert(L, 1); 02679 return Service_provides(L); 02680 } 02681 02682 static int rtt_services(lua_State *L) 02683 { 02684 push_vect_str(L, PluginLoader::Instance()->listServices()); 02685 return 1; 02686 } 02687 02688 static int rtt_typekits(lua_State *L) 02689 { 02690 push_vect_str(L, PluginLoader::Instance()->listTypekits()); 02691 return 1; 02692 } 02693 02694 static int rtt_types(lua_State *L) 02695 { 02696 push_vect_str(L, TypeInfoRepository::Instance()->getTypes()); 02697 return 1; 02698 } 02699 02700 static const struct luaL_Reg rtt_f [] = { 02701 {"getTime", getTime }, 02702 {"sleep", rtt_sleep }, 02703 {"getTC", getTC }, 02704 {"globals_getNames", globals_getNames }, 02705 {"globals_get", globals_get }, 02706 {"provides", provides_global }, 02707 {"services", rtt_services }, 02708 {"typekits", rtt_typekits }, 02709 {"types", rtt_types }, 02710 {"setLogLevel", Logger_setLogLevel }, 02711 {"getLogLevel", Logger_getLogLevel }, 02712 {"log", Logger_log }, 02713 {"logl", Logger_logl }, 02714 {NULL, NULL} 02715 }; 02716 02717 extern "C" int luaopen_rtt(lua_State *L); 02718 02719 int luaopen_rtt(lua_State *L) 02720 { 02721 lua_newtable(L); 02722 lua_replace(L, LUA_ENVIRONINDEX); 02723 02724 luaL_newmetatable(L, "__dead__"); 02725 02726 /* register MyObj 02727 * 1. line creates metatable MyObj and registers name in registry 02728 * 2. line duplicates metatable 02729 * 3. line sets metatable[__index]=metatable 02730 * (more precisely: table at -2 [__index] = top_of_stack, pops top of stack) 02731 * 4. line register methods in metatable 02732 * 5. line registers free functions in global mystuff.MyObj table 02733 */ 02734 luaL_newmetatable(L, "TaskContext"); 02735 lua_pushvalue(L, -1); /* duplicates metatable */ 02736 lua_setfield(L, -2, "__index"); 02737 luaL_register(L, NULL, TaskContext_m); 02738 luaL_register(L, "rtt.TaskContext", TaskContext_f); 02739 02740 luaL_newmetatable(L, "Operation"); 02741 lua_pushvalue(L, -1); 02742 lua_setfield(L, -2, "__index"); 02743 luaL_register(L, NULL, Operation_m); 02744 luaL_register(L, "rtt.Operation", Operation_f); 02745 02746 luaL_newmetatable(L, "Service"); 02747 lua_pushvalue(L, -1); 02748 lua_setfield(L, -2, "__index"); 02749 luaL_register(L, NULL, Service_m); 02750 luaL_register(L, "rtt.Service", Service_f); 02751 02752 luaL_newmetatable(L, "ServiceRequester"); 02753 lua_pushvalue(L, -1); 02754 lua_setfield(L, -2, "__index"); 02755 luaL_register(L, NULL, ServiceRequester_m); 02756 luaL_register(L, "rtt.ServiceRequester", ServiceRequester_f); 02757 02758 luaL_newmetatable(L, "SendHandle"); 02759 lua_pushvalue(L, -1); /* duplicates metatable */ 02760 lua_setfield(L, -2, "__index"); 02761 luaL_register(L, NULL, SendHandle_m); 02762 luaL_register(L, "rtt.SendHandle", SendHandle_f); 02763 02764 luaL_newmetatable(L, "InputPort"); 02765 lua_pushvalue(L, -1); /* duplicates metatable */ 02766 lua_setfield(L, -2, "__index"); 02767 luaL_register(L, NULL, InputPort_m); 02768 luaL_register(L, "rtt.InputPort", InputPort_f); 02769 02770 luaL_newmetatable(L, "OutputPort"); 02771 lua_pushvalue(L, -1); /* duplicates metatable */ 02772 lua_setfield(L, -2, "__index"); 02773 luaL_register(L, NULL, OutputPort_m); 02774 luaL_register(L, "rtt.OutputPort", OutputPort_f); 02775 02776 luaL_newmetatable(L, "Variable"); 02777 lua_pushvalue(L, -1); /* duplicates metatable */ 02778 lua_setfield(L, -2, "__index"); 02779 luaL_register(L, NULL, Variable_m); 02780 luaL_register(L, "rtt.Variable", Variable_f); 02781 02782 luaL_newmetatable(L, "Property"); 02783 lua_pushvalue(L, -1); /* duplicates metatable */ 02784 lua_setfield(L, -2, "__index"); 02785 luaL_register(L, NULL, Property_m); 02786 luaL_register(L, "rtt.Property", Property_f); 02787 02788 luaL_newmetatable(L, "EEHook"); 02789 lua_pushvalue(L, -1); /* duplicates metatable */ 02790 lua_setfield(L, -2, "__index"); 02791 luaL_register(L, NULL, EEHook_m); 02792 luaL_register(L, "rtt.EEHook", EEHook_f); 02793 02794 /* misc toplevel functions */ 02795 luaL_register(L, "rtt", rtt_f); 02796 02797 return 1; 02798 } 02799 02800 /* store the TC to be returned by getTC() in registry */ 02801 int set_context_tc(TaskContext *tc, lua_State *L) 02802 { 02803 TaskContext **new_tc; 02804 lua_pushstring(L, "this_TC"); 02805 new_tc = (TaskContext**) lua_newuserdata(L, sizeof(TaskContext*)); 02806 *new_tc = (TaskContext*) tc; 02807 luaL_getmetatable(L, "TaskContext"); 02808 lua_setmetatable(L, -2); 02809 lua_rawset(L, LUA_REGISTRYINDEX); 02810 return 0; 02811 } 02812 02813 02814 /* call a zero arity function with a boolean return value 02815 * used to call various hooks */ 02816 bool call_func(lua_State *L, const char *fname, TaskContext *tc, 02817 int require_function, int require_result) 02818 { 02819 bool ret = true; 02820 int num_res = (require_result != 0) ? 1 : 0; 02821 lua_getglobal(L, fname); 02822 02823 if(lua_isnil(L, -1)) { 02824 lua_pop(L, 1); 02825 if(require_function) 02826 luaL_error(L, "%s: no (required) Lua function %s", tc->getName().c_str(), fname); 02827 else 02828 goto out; 02829 } 02830 02831 if (lua_pcall(L, 0, num_res, 0) != 0) { 02832 Logger::log(Logger::Error) << "LuaComponent '"<< tc->getName() <<"': error calling function " 02833 << fname << ": " << lua_tostring(L, -1) << endlog(); 02834 ret = false; 02835 goto out; 02836 } 02837 02838 if(require_result) { 02839 if (!lua_isboolean(L, -1)) { 02840 Logger::log(Logger::Error) << "LuaComponent '" << tc->getName() << "': " << fname 02841 << " must return a bool but returned a " 02842 << lua_typename(L, lua_type(L, -1)) << endlog(); 02843 ret = false; 02844 goto out; 02845 } 02846 ret = lua_toboolean(L, -1); 02847 lua_pop(L, 1); /* pop result */ 02848 } 02849 out: 02850 return ret; 02851 }