OrocosComponentLibrary
2.7.0
|
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 * Attribute (boxed) 01060 ***************************************************************/ 01061 01062 gen_push_bxptr(Attribute_push, "Attribute", AttributeBase) 01063 01064 static int Attribute_new(lua_State *L) 01065 { 01066 const char *type, *name; 01067 AttributeBase *pb; 01068 int argc = lua_gettop(L); 01069 type = luaL_checkstring(L, 1); 01070 01071 /* name and description are optional */ 01072 name = (argc > 1) ? luaL_checkstring(L, 2) : ""; 01073 01074 types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type); 01075 01076 if(!ti) 01077 luaL_error(L, "Attribute.new: unknown type %s", type); 01078 01079 pb = ti->buildAttribute(name); 01080 Attribute_push(L, pb); 01081 return 1; 01082 } 01083 01084 static int Attribute_get(lua_State *L) 01085 { 01086 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase)); 01087 Variable_push_coerce(L, pb->getDataSource()); 01088 return 1; 01089 } 01090 01091 static int Attribute_getRaw(lua_State *L) 01092 { 01093 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase)); 01094 luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(pb->getDataSource()); 01095 return 1; 01096 } 01097 01098 static int Attribute_set(lua_State *L) 01099 { 01100 DataSourceBase::shared_ptr newdsb; 01101 DataSourceBase::shared_ptr *newdsbp; 01102 DataSourceBase::shared_ptr propdsb; 01103 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase)); 01104 propdsb = pb->getDataSource(); 01105 01106 /* assigning a DSB */ 01107 if ((newdsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01108 newdsb = *newdsbp; 01109 if(!propdsb->update(newdsb.get())) 01110 luaL_error(L, "Attribute.set: failed to assign type %s to type %s", 01111 newdsb->getType().c_str(), propdsb->getType().c_str()); 01112 } else { /* assigning a Lua value */ 01113 Variable_fromlua(L, propdsb, 2); 01114 } 01115 return 1; 01116 } 01117 01118 static int Attribute_info(lua_State *L) 01119 { 01120 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase)); 01121 lua_newtable(L); 01122 lua_pushstring(L, "name"); lua_pushstring(L, pb->getName().c_str()); lua_rawset(L, -3); 01123 lua_pushstring(L, "type"); lua_pushstring(L, pb->getDataSource()->getType().c_str()); lua_rawset(L, -3); 01124 return 1; 01125 } 01126 01127 #if NOT_USED_YET 01128 /* 01129 * Race condition if we collect properties: if we add this attribute to 01130 * a TC and our life ends before that of the TC, the attribute will be 01131 * deleted before the TaskContext. 01132 */ 01133 static int Attribute_gc(lua_State *L) 01134 { 01135 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase)); 01136 delete pb; 01137 return 0; 01138 } 01139 #endif 01140 01141 01142 /* only explicit destruction allowed */ 01143 static int Attribute_del(lua_State *L) 01144 { 01145 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase)); 01146 delete pb; 01147 01148 /* this prevents calling rtt methods which would cause a crash */ 01149 luaL_getmetatable(L, "__dead__"); 01150 lua_setmetatable(L, -2); 01151 return 0; 01152 } 01153 01154 /* indexability of properties */ 01155 /* 01156 * this is a dispatcher which checks if the key is a method, otherwise 01157 * calls get for looking up the field. Inspired by 01158 * http://lua-users.org/wiki/ObjectProperties 01159 */ 01160 static int Attribute_index(lua_State *L) 01161 { 01162 const char* key = luaL_checkstring(L, 2); 01163 01164 lua_getmetatable(L, 1); 01165 lua_getfield(L, -1, key); /* this actually calls the method */ 01166 01167 /* Either key is name of a method in the metatable */ 01168 if(!lua_isnil(L, -1)) 01169 return 1; 01170 01171 lua_settop(L, 2); /* reset stack */ 01172 Attribute_get(L); /* pushes attribute var */ 01173 lua_replace(L, 1); /* replace prop with var */ 01174 return Variable_index(L); 01175 } 01176 01177 static int Attribute_newindex(lua_State *L) 01178 { 01179 Attribute_get(L); 01180 lua_replace(L, 1); 01181 return Variable_newindex(L); 01182 } 01183 01184 static const struct luaL_Reg Attribute_f [] = { 01185 {"new", Attribute_new }, 01186 {"get", Attribute_get }, 01187 {"getRaw", Attribute_getRaw }, 01188 {"set", Attribute_set }, 01189 {"info", Attribute_info }, 01190 {"delete", Attribute_del }, 01191 {NULL, NULL} 01192 }; 01193 01194 static const struct luaL_Reg Attribute_m [] = { 01195 {"get", Attribute_get }, 01196 {"getRaw", Attribute_getRaw }, 01197 {"set", Attribute_set }, 01198 {"info", Attribute_info }, 01199 // todo: shall we or not? s.o. {"__gc", Attribute_gc }, 01200 {"delete", Attribute_del }, 01201 {"__index", Attribute_index }, 01202 {"__newindex", Attribute_newindex }, 01203 {NULL, NULL} 01204 }; 01205 01206 /*************************************************************** 01207 * Ports (boxed) 01208 ***************************************************************/ 01209 01210 /* both input or output */ 01211 static int Port_info(lua_State *L) 01212 { 01213 int arg_type; 01214 const char* port_type = NULL; 01215 PortInterface **pip; 01216 PortInterface *pi = NULL; 01217 01218 if((pip = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) { 01219 pi = *pip; 01220 port_type = "in"; 01221 } else if((pip = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) { 01222 pi = *pip; 01223 port_type = "out"; 01224 } 01225 else { 01226 arg_type = lua_type(L, 1); 01227 luaL_error(L, "Port.info: invalid argument, expected Port, got %s", 01228 lua_typename(L, arg_type)); 01229 } 01230 01231 lua_newtable(L); 01232 lua_pushstring(L, "name"); lua_pushstring(L, pi->getName().c_str()); lua_rawset(L, -3); 01233 lua_pushstring(L, "desc"); lua_pushstring(L, pi->getDescription().c_str()); lua_rawset(L, -3); 01234 lua_pushstring(L, "connected"); lua_pushboolean(L, pi->connected()); lua_rawset(L, -3); 01235 lua_pushstring(L, "isLocal"); lua_pushboolean(L, pi->isLocal()); lua_rawset(L, -3); 01236 lua_pushstring(L, "type"); lua_pushstring(L, pi->getTypeInfo()->getTypeName().c_str()); lua_rawset(L, -3); 01237 lua_pushstring(L, "porttype"); lua_pushstring(L, port_type); lua_rawset(L, -3); 01238 01239 return 1; 01240 } 01241 01242 static int Port_connect(lua_State *L) 01243 { 01244 int arg_type, ret; 01245 PortInterface **pip1, **pip2; 01246 PortInterface *pi1 = NULL; 01247 PortInterface *pi2 = NULL; 01248 ConnPolicy **cpp; 01249 ConnPolicy *cp = NULL; 01250 01251 if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) { 01252 pi1= *pip1; 01253 } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) { 01254 pi1= *pip1; 01255 } 01256 else { 01257 arg_type = lua_type(L, 1); 01258 luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s", 01259 lua_typename(L, arg_type)); 01260 } 01261 if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) { 01262 pi2= *pip2; 01263 } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) { 01264 pi2= *pip2; 01265 } 01266 else { 01267 arg_type = lua_type(L, 2); 01268 luaL_error(L, "Port.connect: invalid argument 2, expected Port, got %s", 01269 lua_typename(L, arg_type)); 01270 } 01271 01272 if((cpp = (ConnPolicy**) luaL_testudata(L, 3, "ConnPolicy")) != NULL) { 01273 cp=*cpp; 01274 } 01275 01276 if ( cp ) 01277 ret = pi1->connectTo(pi2, *cp); 01278 else 01279 ret = pi1->connectTo(pi2); 01280 01281 lua_pushboolean(L, ret); 01282 01283 return 1; 01284 } 01285 01286 static int Port_disconnect(lua_State *L) 01287 { 01288 int arg_type, ret; 01289 PortInterface **pip1, **pip2; 01290 PortInterface *pi1 = NULL; 01291 PortInterface *pi2 = NULL; 01292 01293 if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) { 01294 pi1= *pip1; 01295 } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) { 01296 pi1= *pip1; 01297 } 01298 else { 01299 arg_type = lua_type(L, 1); 01300 luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s", 01301 lua_typename(L, arg_type)); 01302 } 01303 if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) { 01304 pi2= *pip2; 01305 } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) { 01306 pi2= *pip2; 01307 } 01308 01309 if (pi2 != NULL) 01310 ret = pi1->disconnect(pi2); 01311 else{ 01312 pi1->disconnect(); 01313 ret = 1; 01314 } 01315 lua_pushboolean(L, ret); 01316 01317 return 1; 01318 } 01319 01320 01321 01322 /* InputPort (boxed) */ 01323 01324 gen_push_bxptr(InputPort_push, "InputPort", InputPortInterface) 01325 01326 static int InputPort_new(lua_State *L) 01327 { 01328 const char *type, *name, *desc; 01329 InputPortInterface* ipi; 01330 int argc = lua_gettop(L); 01331 01332 type = luaL_checkstring(L, 1); 01333 01334 /* name and description are optional */ 01335 name = (argc > 1) ? luaL_checkstring(L, 2) : ""; 01336 desc = (argc > 2) ? luaL_checkstring(L, 3) : ""; 01337 01338 types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type); 01339 if(ti==0) 01340 luaL_error(L, "InputPort.new: unknown type %s", type); 01341 01342 ipi = ti->inputPort(name); 01343 01344 if(!ipi) 01345 luaL_error(L, "InputPort.new: creating port of type %s failed", type); 01346 01347 ipi->doc(desc); 01348 InputPort_push(L, ipi); 01349 return 1; 01350 } 01351 01352 static int InputPort_read(lua_State *L) 01353 { 01354 int ret = 1; 01355 InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface)); 01356 DataSourceBase::shared_ptr dsb; 01357 DataSourceBase::shared_ptr *dsbp; 01358 FlowStatus fs; 01359 01360 /* if we get don't get a DS to store the result, create one */ 01361 if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) 01362 dsb = *dsbp; 01363 else { 01364 dsb = ip->getTypeInfo()->buildValue(); 01365 ret = 2; 01366 } 01367 01368 fs = ip->read(dsb); 01369 01370 if(fs == NoData) lua_pushstring(L, "NoData"); 01371 else if (fs == NewData) lua_pushstring(L, "NewData"); 01372 else if (fs == OldData) lua_pushstring(L, "OldData"); 01373 else luaL_error(L, "InputPort.read: unknown FlowStatus returned"); 01374 01375 if(ret>1) 01376 Variable_push_coerce(L, dsb); 01377 01378 return ret; 01379 } 01380 01381 #ifdef NOT_USED_YET 01382 static int InputPort_gc(lua_State *L) 01383 { 01384 InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface)); 01385 delete ip; 01386 return 0; 01387 } 01388 #endif 01389 01390 /* only explicit destruction allowed */ 01391 static int InputPort_del(lua_State *L) 01392 { 01393 InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface)); 01394 delete ip; 01395 01396 /* this prevents calling rtt methods which would cause a crash */ 01397 luaL_getmetatable(L, "__dead__"); 01398 lua_setmetatable(L, -2); 01399 return 0; 01400 } 01401 01402 static const struct luaL_Reg InputPort_f [] = { 01403 {"new", InputPort_new }, 01404 {"read", InputPort_read }, 01405 {"info", Port_info }, 01406 {"connect", Port_connect }, 01407 {"disconnect", Port_disconnect }, 01408 {"delete", InputPort_del }, 01409 {NULL, NULL} 01410 }; 01411 01412 static const struct luaL_Reg InputPort_m [] = { 01413 {"read", InputPort_read }, 01414 {"info", Port_info }, 01415 {"delete", InputPort_del }, 01416 {"connect", Port_connect }, 01417 {"disconnect", Port_disconnect }, 01418 /* {"__gc", InputPort_gc }, */ 01419 {NULL, NULL} 01420 }; 01421 01422 /* OutputPort */ 01423 01424 gen_push_bxptr(OutputPort_push, "OutputPort", OutputPortInterface) 01425 01426 01427 static int OutputPort_new(lua_State *L) 01428 { 01429 const char *type, *name, *desc; 01430 OutputPortInterface* opi; 01431 int argc = lua_gettop(L); 01432 01433 type = luaL_checkstring(L, 1); 01434 01435 /* name and description are optional */ 01436 name = (argc > 1) ? luaL_checkstring(L, 2) : ""; 01437 desc = (argc > 2) ? luaL_checkstring(L, 3) : ""; 01438 01439 types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type); 01440 01441 if(ti==0) 01442 luaL_error(L, "OutputPort.new: unknown type %s", type); 01443 01444 opi = ti->outputPort(name); 01445 01446 if(!opi) 01447 luaL_error(L, "OutputPort.new: creating port of type %s failed", type); 01448 01449 opi->doc(desc); 01450 OutputPort_push(L, opi); 01451 return 1; 01452 } 01453 01454 static int OutputPort_write(lua_State *L) 01455 { 01456 DataSourceBase::shared_ptr dsb; 01457 DataSourceBase::shared_ptr *dsbp; 01458 01459 OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface)); 01460 01461 /* fastpath: Variable argument */ 01462 if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01463 dsb = *dsbp; 01464 } else { 01465 /* slowpath: convert lua value to dsb */ 01466 dsb = Variable_fromlua(L, op->getTypeInfo(), 2); 01467 } 01468 op->write(dsb); 01469 return 0; 01470 } 01471 01472 #ifdef NOT_USED_YET 01473 static int OutputPort_gc(lua_State *L) 01474 { 01475 OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface)); 01476 delete op; 01477 return 0; 01478 } 01479 #endif 01480 01481 /* only explicit destruction allowed */ 01482 static int OutputPort_del(lua_State *L) 01483 { 01484 OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface)); 01485 delete op; 01486 01487 /* this prevents calling rtt methods which would cause a crash */ 01488 luaL_getmetatable(L, "__dead__"); 01489 lua_setmetatable(L, -2); 01490 return 0; 01491 } 01492 01493 static const struct luaL_Reg OutputPort_f [] = { 01494 {"new", OutputPort_new }, 01495 {"write", OutputPort_write }, 01496 {"info", Port_info }, 01497 {"connect", Port_connect }, 01498 {"disconnect", Port_disconnect }, 01499 {"delete", OutputPort_del }, 01500 {NULL, NULL} 01501 }; 01502 01503 static const struct luaL_Reg OutputPort_m [] = { 01504 {"write", OutputPort_write }, 01505 {"info", Port_info }, 01506 {"connect", Port_connect }, 01507 {"disconnect", Port_disconnect }, 01508 {"delete", OutputPort_del }, 01509 /* {"__gc", OutputPort_gc }, */ 01510 {NULL, NULL} 01511 }; 01512 01513 /*************************************************************** 01514 * Operation 01515 ***************************************************************/ 01516 01517 struct OperationHandle { 01518 OperationInterfacePart *oip; 01519 OperationCallerC *occ; 01520 unsigned int arity; 01521 bool is_void; 01522 01523 /* we need to store references to the dsb which we created 01524 on-the-fly, because the ReferenceDSB does not hold a 01525 shared_ptr, and hence these DSN might get destructed 01526 before/during the call 01527 */ 01528 std::vector<base::DataSourceBase::shared_ptr> dsb_store; 01529 std::vector<internal::Reference*> args; 01530 base::DataSourceBase::shared_ptr call_dsb; 01531 base::DataSourceBase::shared_ptr ret_dsb; 01532 }; 01533 01534 template<typename T> 01535 int OperationGC(lua_State* L) 01536 { 01537 T* oh = (T*) lua_touserdata(L, 1); 01538 delete oh->occ; 01539 reinterpret_cast<T*>(lua_touserdata(L, 1))->~T(); 01540 return 0; 01541 } 01542 01543 static int Operation_info(lua_State *L) 01544 { 01545 int i=1; 01546 std::vector<ArgumentDescription> args; 01547 OperationHandle *op = luaM_checkudata_mt(L, 1, "Operation", OperationHandle); 01548 01549 lua_pushstring(L, op->oip->getName().c_str()); /* name */ 01550 lua_pushstring(L, op->oip->description().c_str()); /* description */ 01551 lua_pushstring(L, op->oip->resultType().c_str()); /* result type */ 01552 lua_pushinteger(L, op->arity); /* arity */ 01553 01554 args = op->oip->getArgumentList(); 01555 01556 lua_newtable(L); 01557 01558 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) { 01559 lua_newtable(L); 01560 lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3); 01561 lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3); 01562 lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3); 01563 lua_rawseti(L, -2, i++); 01564 } 01565 return 5; 01566 } 01567 01568 static int __Operation_call(lua_State *L) 01569 { 01570 bool ret; 01571 DataSourceBase::shared_ptr dsb, *dsbp; 01572 01573 OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle); 01574 OperationInterfacePart *oip = oh->oip; 01575 unsigned int argc = lua_gettop(L); 01576 01577 if(oh->arity != argc-1) 01578 luaL_error(L, "Operation.call: wrong number of args. expected %d, got %d", oh->arity, argc-1); 01579 01580 /* update dsbs */ 01581 for(unsigned int arg=2; arg<=argc; arg++) { 01582 /* fastpath: Variable argument */ 01583 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01584 dsb = *dsbp; 01585 } else { 01586 /* slowpath: convert lua value to dsb */ 01587 dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg); 01588 /* this dsb must outlive occ->call (see comment in 01589 OperationHandle def.): */ 01590 oh->dsb_store.push_back(dsb); 01591 } 01592 if(!dsb->isAssignable()) 01593 luaL_error(L, "Operation.call: argument %d is not assignable.", arg-1); 01594 01595 ret = oh->args[arg-2]->setReference(dsb); 01596 if (!ret) 01597 luaL_error(L, "Operation_call: setReference failed, wrong type of argument?"); 01598 } 01599 01600 if(!oh->occ->call()) 01601 luaL_error(L, "Operation.call: call failed."); 01602 01603 oh->dsb_store.clear(); 01604 01605 if(!oh->is_void) 01606 Variable_push_coerce(L, oh->ret_dsb); 01607 else 01608 lua_pushnil(L); 01609 return 1; 01610 } 01611 01612 static int __Operation_send(lua_State *L) 01613 { 01614 DataSourceBase::shared_ptr dsb, *dsbp; 01615 01616 OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle); 01617 OperationInterfacePart *oip = oh->oip; 01618 unsigned int argc = lua_gettop(L); 01619 01620 if(oh->arity != argc-1) 01621 luaL_error(L, "Operation.send: wrong number of args. expected %d, got %d", oh->arity, argc-1); 01622 01623 /* update dsbs */ 01624 for(unsigned int arg=2; arg<=argc; arg++) { 01625 /* fastpath: Variable argument */ 01626 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) { 01627 dsb = *dsbp; 01628 } else { 01629 /* slowpath: convert lua value to dsb */ 01630 dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg); 01631 /* this dsb must outlive occ->call (see comment in 01632 OperationHandle def.): */ 01633 oh->dsb_store.push_back(dsb); 01634 } 01635 oh->args[arg-2]->setReference(dsb); 01636 } 01637 01638 luaM_pushobject_mt(L, "SendHandle", SendHandleC)(oh->occ->send()); 01639 return 1; 01640 } 01641 01642 static int Operation_call(lua_State *L) 01643 { 01644 int ret; 01645 try { 01646 ret = __Operation_call(L); 01647 } catch(const std::exception &exc) { 01648 luaL_error(L, "Operation.call: caught exception '%s'", exc.what()); 01649 } catch(...) { 01650 luaL_error(L, "Operation.call: caught unknown exception"); 01651 } 01652 return ret; 01653 } 01654 01655 static int Operation_send(lua_State *L) 01656 { 01657 int ret; 01658 try { 01659 ret = __Operation_send(L); 01660 } catch(const std::exception &exc) { 01661 luaL_error(L, "Operation.send: caught exception '%s'", exc.what()); 01662 } catch(...) { 01663 luaL_error(L, "Operation.send: caught unknown exception"); 01664 } 01665 return ret; 01666 } 01667 01668 01669 static const struct luaL_Reg Operation_f [] = { 01670 { "info", Operation_info }, 01671 { "call", Operation_call }, 01672 { "send", Operation_send }, 01673 { NULL, NULL } 01674 01675 }; 01676 01677 static const struct luaL_Reg Operation_m [] = { 01678 { "info", Operation_info }, 01679 { "send", Operation_send }, 01680 { "__call", Operation_call }, 01681 { "__gc", OperationGC<OperationHandle> }, 01682 { NULL, NULL } 01683 }; 01684 01685 /*************************************************************** 01686 * Service (boxed) 01687 ***************************************************************/ 01688 01689 static int Service_getName(lua_State *L) 01690 { 01691 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01692 lua_pushstring(L, srv->getName().c_str()); 01693 return 1; 01694 } 01695 01696 static int Service_doc(lua_State *L) 01697 { 01698 int ret; 01699 const char* doc; 01700 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01701 if(lua_gettop(L) == 1) { 01702 lua_pushstring(L, srv->doc().c_str()); 01703 ret = 1; 01704 } else { 01705 doc = luaL_checkstring(L, 2); 01706 srv->doc(doc); 01707 ret = 0; 01708 } 01709 01710 return ret; 01711 } 01712 01713 static int Service_getProviderNames(lua_State *L) 01714 { 01715 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01716 push_vect_str(L, srv->getProviderNames()); 01717 return 1; 01718 } 01719 01720 static int Service_getOperationNames(lua_State *L) 01721 { 01722 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01723 push_vect_str(L, srv->getOperationNames()); 01724 return 1; 01725 } 01726 01727 01728 static int Service_hasOperation(lua_State *L) 01729 { 01730 int ret; 01731 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01732 const char* op = luaL_checkstring(L, 2); 01733 ret = srv->hasOperation(op); 01734 lua_pushboolean(L, ret); 01735 return 1; 01736 } 01737 01738 static int Service_getPortNames(lua_State *L) 01739 { 01740 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01741 push_vect_str(L, srv->getPortNames()); 01742 return 1; 01743 } 01744 01745 static int Service_provides(lua_State *L) 01746 { 01747 int ret, i, argc; 01748 const char* subsrv_str; 01749 Service::shared_ptr srv, subsrv; 01750 01751 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01752 argc=lua_gettop(L); 01753 01754 /* return "this" if no args given */ 01755 if(argc == 1) { 01756 ret = 1; 01757 goto out; 01758 } 01759 01760 for(i=2; i<=argc; i++) { 01761 subsrv_str = luaL_checkstring(L, i); 01762 subsrv = srv->getService(subsrv_str); 01763 if (subsrv == 0) 01764 luaL_error(L, "Service.provides: no subservice %s of service %s", 01765 subsrv_str, srv->getName().c_str() ); 01766 else 01767 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(subsrv); 01768 } 01769 ret = argc - 1; 01770 01771 out: 01772 return ret; 01773 } 01774 01775 static int Service_getOperation(lua_State *L) 01776 { 01777 const char *op_str; 01778 OperationInterfacePart *oip; 01779 Service::shared_ptr srv; 01780 DataSourceBase::shared_ptr dsb; 01781 const types::TypeInfo *ti; 01782 OperationHandle *oh; 01783 TaskContext *this_tc; 01784 01785 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01786 op_str = luaL_checkstring(L, 2); 01787 oip = srv->getOperation(op_str); 01788 01789 if(!oip) 01790 luaL_error(L, "Service_getOperation: service %s has no operation %s", 01791 srv->getName().c_str(), op_str); 01792 01793 oh = (OperationHandle*) luaM_pushobject_mt(L, "Operation", OperationHandle)(); 01794 oh->oip = oip; 01795 oh->arity = oip->arity(); 01796 oh->args.reserve(oh->arity); 01797 this_tc = __getTC(L); 01798 01799 oh->occ = new OperationCallerC(oip, op_str, this_tc->engine()); 01800 01801 /* create args 01802 * getArgumentType(0) is return value 01803 */ 01804 for(unsigned int arg=1; arg <= oh->arity; arg++) { 01805 std::string type = oip->getArgumentType(arg)->getTypeName(); 01806 ti = types::TypeInfoRepository::Instance()->type(type); 01807 if(!ti) 01808 luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for arg %d of type '%s'", 01809 op_str, arg, type.c_str()); 01810 01811 dsb = ti->buildReference((void*) 0xdeadbeef); 01812 if(!dsb) 01813 luaL_error(L, "Operation.call: '%s', failed to build DSB for arg %d of type '%s'", 01814 op_str, arg, type.c_str()); 01815 01816 oh->args.push_back(dynamic_cast<internal::Reference*>(dsb.get())); 01817 oh->occ->arg(dsb); 01818 } 01819 01820 /* return value */ 01821 if(oip->resultType() != "void"){ 01822 ti = oip->getArgumentType(0); // 0 == return type 01823 if(!ti) 01824 luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for return value of type '%s'", 01825 op_str, oip->resultType().c_str()); 01826 oh->ret_dsb=ti->buildValue(); 01827 if(!oh->ret_dsb) 01828 luaL_error(L, "Operation.call: '%s', failed to build DSB for return value of type '%s'", 01829 op_str, oip->resultType().c_str()); 01830 01831 oh->occ->ret(oh->ret_dsb); 01832 oh->is_void=false; 01833 } else { 01834 oh->is_void=true; 01835 } 01836 01837 if(!oh->occ->ready()) 01838 luaL_error(L, "Service.getOperation: OperationCallerC not ready!"); 01839 01840 return 1; 01841 } 01842 01843 static int Service_getPort(lua_State *L) 01844 { 01845 const char* name; 01846 PortInterface *pi; 01847 InputPortInterface *ipi; 01848 OutputPortInterface *opi; 01849 01850 Service::shared_ptr srv; 01851 01852 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01853 name = luaL_checkstring(L, 2); 01854 01855 pi = srv->getPort(name); 01856 if(!pi) 01857 luaL_error(L, "Service.getPort: service %s has no port %", 01858 srv->getName().c_str(), name); 01859 01860 /* input or output? */ 01861 if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL) 01862 InputPort_push(L, ipi); 01863 else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL) 01864 OutputPort_push(L, opi); 01865 else 01866 luaL_error(L, "Service.getPort: unknown port type returned"); 01867 01868 return 1; 01869 } 01870 01871 static int Service_getProperty(lua_State *L) 01872 { 01873 const char *name; 01874 PropertyBase *prop; 01875 01876 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01877 name = luaL_checkstring(L, 2); 01878 01879 prop = srv->getProperty(name); 01880 01881 if(!prop) 01882 luaL_error(L, "%s failed. No such property", __FILE__); 01883 01884 Property_push(L, prop); 01885 return 1; 01886 } 01887 01888 static int Service_getPropertyNames(lua_State *L) 01889 { 01890 Service::shared_ptr srv; 01891 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01892 std::vector<std::string> plist = srv->properties()->list(); 01893 push_vect_str(L, plist); 01894 return 1; 01895 } 01896 01897 static int Service_getProperties(lua_State *L) 01898 { 01899 Service::shared_ptr srv; 01900 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01901 vector<PropertyBase*> props = srv->properties()->getProperties(); 01902 01903 int key = 1; 01904 lua_createtable(L, props.size(), 0); 01905 for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) { 01906 Property_push(L, *it); 01907 lua_rawseti(L, -2, key++); 01908 } 01909 01910 return 1; 01911 } 01912 01913 static int Service_getAttribute(lua_State *L) 01914 { 01915 const char *name; 01916 AttributeBase *prop; 01917 01918 Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01919 name = luaL_checkstring(L, 2); 01920 01921 prop = srv->getAttribute(name); 01922 01923 if(!prop) 01924 luaL_error(L, "%s failed. No such Attribute", __FILE__); 01925 01926 Attribute_push(L, prop); 01927 return 1; 01928 } 01929 01930 static int Service_getAttributeNames(lua_State *L) 01931 { 01932 Service::shared_ptr srv; 01933 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01934 std::vector<std::string> plist = srv->getAttributeNames(); 01935 push_vect_str(L, plist); 01936 return 1; 01937 } 01938 01939 static int Service_getAttributes(lua_State *L) 01940 { 01941 Service::shared_ptr srv; 01942 srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr)); 01943 vector<AttributeBase*> props = srv->getValues(); 01944 01945 int key = 1; 01946 lua_createtable(L, props.size(), 0); 01947 for(vector<AttributeBase*>::iterator it = props.begin(); it != props.end(); ++it) { 01948 Attribute_push(L, *it); 01949 lua_rawseti(L, -2, key++); 01950 } 01951 01952 return 1; 01953 } 01954 01955 static const struct luaL_Reg Service_f [] = { 01956 { "getName", Service_getName }, 01957 { "doc", Service_doc }, 01958 { "getProviderNames", Service_getProviderNames }, 01959 { "getOperationNames", Service_getOperationNames }, 01960 { "hasOperation", Service_hasOperation }, 01961 { "getPortNames", Service_getPortNames }, 01962 { "provides", Service_provides }, 01963 { "getOperation", Service_getOperation }, 01964 { "getPort", Service_getPort }, 01965 { "getProperty", Service_getProperty }, 01966 { "getProperties", Service_getProperties }, 01967 { "getPropertyNames", Service_getPropertyNames }, 01968 { "getAttribute", Service_getAttribute }, 01969 { "getAttributes", Service_getAttributes }, 01970 { "getAttributeNames", Service_getAttributeNames }, 01971 { NULL, NULL } 01972 }; 01973 01974 static const struct luaL_Reg Service_m [] = { 01975 { "getName", Service_getName }, 01976 { "doc", Service_doc }, 01977 { "getProviderNames", Service_getProviderNames }, 01978 { "getOperationNames", Service_getOperationNames }, 01979 { "hasOperation", Service_hasOperation }, 01980 { "getPortNames", Service_getPortNames }, 01981 { "provides", Service_provides }, 01982 { "getOperation", Service_getOperation }, 01983 { "getPort", Service_getPort }, 01984 { "getProperty", Service_getProperty }, 01985 { "getProperties", Service_getProperties }, 01986 { "getPropertyNames", Service_getPropertyNames }, 01987 { "getAttribute", Service_getAttribute }, 01988 { "getAttributes", Service_getAttributes }, 01989 { "getAttributeNames", Service_getAttributeNames }, 01990 { "__gc", GCMethod<Service::shared_ptr> }, 01991 { NULL, NULL } 01992 }; 01993 01994 /*************************************************************** 01995 * ServiceRequester 01996 ***************************************************************/ 01997 01998 gen_push_bxptr(ServiceRequester_push, "ServiceRequester", ServiceRequester) 01999 02000 static int ServiceRequester_getRequestName(lua_State *L) 02001 { 02002 ServiceRequester *sr; 02003 02004 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 02005 lua_pushstring(L, sr->getRequestName().c_str()); 02006 return 1; 02007 } 02008 02009 static int ServiceRequester_getRequesterNames(lua_State *L) 02010 { 02011 ServiceRequester *sr; 02012 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 02013 push_vect_str(L, sr->getRequesterNames()); 02014 return 1; 02015 } 02016 02017 static int ServiceRequester_ready(lua_State *L) 02018 { 02019 int ret; 02020 ServiceRequester *sr; 02021 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 02022 ret = sr->ready(); 02023 lua_pushboolean(L, ret); 02024 return 1; 02025 } 02026 02027 static int ServiceRequester_disconnect(lua_State *L) 02028 { 02029 ServiceRequester *sr; 02030 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 02031 sr->disconnect(); 02032 return 0; 02033 } 02034 02035 static int ServiceRequester_requires(lua_State *L) 02036 { 02037 int argc, ret, i; 02038 const char* subsr_str; 02039 ServiceRequester *sr; 02040 ServiceRequester::shared_ptr subsr; 02041 02042 sr = *(luaM_checkudata_bx(L, 1, ServiceRequester)); 02043 argc = lua_gettop(L); 02044 02045 /* return "this" if no args given */ 02046 if(argc == 1) { 02047 ret = 1; 02048 goto out; 02049 } 02050 02051 for(i=2; i<=argc; i++) { 02052 subsr_str = luaL_checkstring(L, i); 02053 subsr = sr->requires(subsr_str); 02054 if (subsr == 0) 02055 luaL_error(L, "ServiceRequester: no required subservice %s of service %s", 02056 subsr_str, sr->getRequestName().c_str()); 02057 else 02058 ServiceRequester_push(L, subsr.get()); 02059 } 02060 ret = argc - 1; 02061 02062 out: 02063 return ret; 02064 } 02065 02066 static const struct luaL_Reg ServiceRequester_f [] = { 02067 { "getRequestName", ServiceRequester_getRequestName }, 02068 { "getRequesterNames", ServiceRequester_getRequesterNames }, 02069 { "ready", ServiceRequester_ready }, 02070 { "disconnect", ServiceRequester_disconnect }, 02071 { "requires", ServiceRequester_requires }, 02072 { NULL, NULL } 02073 }; 02074 02075 static const struct luaL_Reg ServiceRequester_m [] = { 02076 { "getRequestName", ServiceRequester_getRequestName }, 02077 { "getRequesterNames", ServiceRequester_getRequesterNames }, 02078 { "ready", ServiceRequester_ready }, 02079 { "disconnect", ServiceRequester_disconnect }, 02080 { "requires", ServiceRequester_requires }, 02081 { NULL, NULL } 02082 }; 02083 02084 02085 /*************************************************************** 02086 * TaskContext (boxed) 02087 ***************************************************************/ 02088 02089 gen_push_bxptr(TaskContext_push, "TaskContext", TaskContext) 02090 02091 static int TaskContext_getName(lua_State *L) 02092 { 02093 const char *s; 02094 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02095 s = tc->getName().c_str(); 02096 lua_pushstring(L, s); 02097 return 1; 02098 } 02099 02100 static int TaskContext_start(lua_State *L) 02101 { 02102 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02103 bool b = tc->start(); 02104 lua_pushboolean(L, b); 02105 return 1; 02106 } 02107 02108 static int TaskContext_stop(lua_State *L) 02109 { 02110 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02111 bool b = tc->stop(); 02112 lua_pushboolean(L, b); 02113 return 1; 02114 } 02115 02116 static int TaskContext_configure(lua_State *L) 02117 { 02118 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02119 bool ret = tc->configure(); 02120 lua_pushboolean(L, ret); 02121 return 1; 02122 } 02123 02124 static int TaskContext_activate(lua_State *L) 02125 { 02126 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02127 bool ret = tc->activate(); 02128 lua_pushboolean(L, ret); 02129 return 1; 02130 } 02131 02132 static int TaskContext_cleanup(lua_State *L) 02133 { 02134 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02135 bool ret = tc->cleanup(); 02136 lua_pushboolean(L, ret); 02137 return 1; 02138 } 02139 02140 static int TaskContext_error(lua_State *L) 02141 { 02142 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02143 tc->error(); 02144 return 0; 02145 } 02146 02147 static int TaskContext_recover(lua_State *L) 02148 { 02149 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02150 bool ret = tc->recover(); 02151 lua_pushboolean(L, ret); 02152 return 1; 02153 } 02154 02155 static int TaskContext_getState(lua_State *L) 02156 { 02157 TaskCore::TaskState ts; 02158 TaskContext **tc = (TaskContext**) luaM_checkudata_bx(L, 1, TaskContext); 02159 ts = (*tc)->getTaskState(); 02160 02161 switch(ts) { 02162 case TaskCore::Init: lua_pushstring(L, "Init"); break; 02163 case TaskCore::PreOperational: lua_pushstring(L, "PreOperational"); break; 02164 case TaskCore::FatalError: lua_pushstring(L, "FatalError"); break; 02165 case TaskCore::Exception: lua_pushstring(L, "Exception"); break; 02166 case TaskCore::Stopped: lua_pushstring(L, "Stopped"); break; 02167 case TaskCore::Running: lua_pushstring(L, "Running"); break; 02168 case TaskCore::RunTimeError: lua_pushstring(L, "RunTimeError"); break; 02169 default: lua_pushstring(L, "unknown"); 02170 } 02171 return 1; 02172 } 02173 02174 /* string-table getPeers(TaskContext self)*/ 02175 /* should better return array of TC's */ 02176 static int TaskContext_getPeers(lua_State *L) 02177 { 02178 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02179 std::vector<std::string> plist = tc->getPeerList(); 02180 push_vect_str(L, plist); 02181 return 1; 02182 } 02183 02184 /* bool addPeer(TaskContext self, TaskContext peer)*/ 02185 static int TaskContext_addPeer(lua_State *L) 02186 { 02187 bool ret; 02188 TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext)); 02189 TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext)); 02190 ret = self->addPeer(peer); 02191 lua_pushboolean(L, ret); 02192 return 1; 02193 } 02194 02195 /* void removePeer(TaskContext self, string peer)*/ 02196 static int TaskContext_removePeer(lua_State *L) 02197 { 02198 std::string peer; 02199 TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext)); 02200 peer = luaL_checkstring(L, 2); 02201 self->removePeer(peer); 02202 return 0; 02203 } 02204 02205 /* TaskContext getPeer(string name) */ 02206 static int TaskContext_getPeer(lua_State *L) 02207 { 02208 std::string strpeer; 02209 TaskContext *peer; 02210 TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext)); 02211 strpeer = luaL_checkstring(L, 2); 02212 peer = self->getPeer(strpeer); 02213 02214 if(!peer) { 02215 luaL_error(L, "TaskContext.getPeer: no peer %s", strpeer.c_str()); 02216 goto out; 02217 } 02218 02219 TaskContext_push(L, peer); 02220 out: 02221 return 1; 02222 } 02223 02224 static int TaskContext_getPortNames(lua_State *L) 02225 { 02226 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02227 std::vector<std::string> plist = tc->ports()->getPortNames(); 02228 push_vect_str(L, plist); 02229 return 1; 02230 } 02231 02232 static int TaskContext_addPort(lua_State *L) 02233 { 02234 const char* name, *desc; 02235 PortInterface **pi; 02236 int argc = lua_gettop(L); 02237 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02238 02239 pi = (PortInterface**) luaL_testudata(L, 2, "InputPort"); 02240 if(pi) goto check_name; 02241 02242 pi = (PortInterface**) luaL_testudata(L, 2, "OutputPort"); 02243 if(pi) goto check_name; 02244 02245 return luaL_error(L, "addPort: invalid argument, not a Port"); 02246 02247 check_name: 02248 if(argc > 2) { 02249 name = luaL_checkstring(L, 3); 02250 (*pi)->setName(name); 02251 } 02252 02253 if(argc > 3) { 02254 desc = luaL_checkstring(L, 4); 02255 (*pi)->doc(desc); 02256 } 02257 02258 tc->ports()->addPort(**pi); 02259 return 0; 02260 } 02261 02262 static int TaskContext_addEventPort(lua_State *L) 02263 { 02264 const char* name, *desc; 02265 InputPortInterface **ipi; 02266 int argc = lua_gettop(L); 02267 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02268 02269 if((ipi = (InputPortInterface**) luaL_testudata(L, 2, "InputPort")) == NULL) 02270 return luaL_error(L, "addEventPort: invalid argument, not an InputPort"); 02271 02272 if(argc > 2) { 02273 name = luaL_checkstring(L, 3); 02274 (*ipi)->setName(name); 02275 } 02276 02277 if(argc > 3) { 02278 desc = luaL_checkstring(L, 4); 02279 (*ipi)->doc(desc); 02280 } 02281 02282 tc->ports()->addEventPort(**ipi); 02283 return 0; 02284 } 02285 02286 static int TaskContext_getPort(lua_State *L) 02287 { 02288 const char* name; 02289 PortInterface *pi; 02290 InputPortInterface *ipi; 02291 OutputPortInterface *opi; 02292 02293 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02294 name = luaL_checkstring(L, 2); 02295 02296 pi = tc->getPort(name); 02297 if(!pi) 02298 luaL_error(L, "TaskContext.getPort: no port %s for taskcontext %s", 02299 name, tc->getName().c_str()); 02300 02301 /* input or output? */ 02302 if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL) 02303 InputPort_push(L, ipi); 02304 else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL) 02305 OutputPort_push(L, opi); 02306 else 02307 luaL_error(L, "TaskContext.getPort: unknown port returned"); 02308 02309 return 1; 02310 } 02311 02312 static int TaskContext_removePort(lua_State *L) 02313 { 02314 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02315 const char *port = luaL_checkstring(L, 2); 02316 tc->ports()->removePort(port); 02317 return 0; 02318 } 02319 02320 static int TaskContext_addProperty(lua_State *L) 02321 { 02322 const char *name, *desc; 02323 int argc = lua_gettop(L); 02324 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02325 PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Property", PropertyBase)); 02326 02327 if(argc > 2) { 02328 name = luaL_checkstring(L, 3); 02329 pb->setName(name); 02330 } 02331 02332 if(argc > 3) { 02333 desc = luaL_checkstring(L, 4); 02334 pb->setDescription(desc); 02335 } 02336 02337 02338 if(!tc->addProperty(*pb)) 02339 luaL_error(L, "TaskContext.addProperty: failed to add property %s.", 02340 pb->getName().c_str()); 02341 02342 return 0; 02343 } 02344 02345 static int TaskContext_getProperty(lua_State *L) 02346 { 02347 const char *name; 02348 PropertyBase *prop; 02349 02350 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02351 name = luaL_checkstring(L, 2); 02352 02353 prop = tc->getProperty(name); 02354 02355 if(!prop) 02356 luaL_error(L, "%s failed. No such property", __FILE__); 02357 02358 Property_push(L, prop); 02359 return 1; 02360 } 02361 02362 02363 static int TaskContext_getPropertyNames(lua_State *L) 02364 { 02365 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02366 std::vector<std::string> plist = tc->properties()->list(); 02367 push_vect_str(L, plist); 02368 return 1; 02369 } 02370 02371 static int TaskContext_getProperties(lua_State *L) 02372 { 02373 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02374 vector<PropertyBase*> props = tc->properties()->getProperties(); 02375 02376 int key = 1; 02377 lua_createtable(L, props.size(), 0); 02378 for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) { 02379 Property_push(L, *it); 02380 lua_rawseti(L, -2, key++); 02381 } 02382 02383 return 1; 02384 } 02385 02386 static int TaskContext_removeProperty(lua_State *L) 02387 { 02388 const char *name; 02389 PropertyBase *prop; 02390 02391 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02392 name = luaL_checkstring(L, 2); 02393 02394 prop = tc->getProperty(name); 02395 02396 if(!prop) 02397 luaL_error(L, "%s failed. No such property", __FILE__); 02398 02399 tc->properties()->remove(prop); 02400 return 0; 02401 } 02402 02403 static int TaskContext_addAttribute(lua_State *L) 02404 { 02405 const char *name, *desc; 02406 int argc = lua_gettop(L); 02407 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02408 AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Attribute", AttributeBase)); 02409 02410 if(argc > 2) { 02411 name = luaL_checkstring(L, 3); 02412 pb->setName(name); 02413 } 02414 02415 if(!tc->addAttribute(*pb)) 02416 luaL_error(L, "TaskContext.addAttribute: failed to add attribute %s.", 02417 pb->getName().c_str()); 02418 02419 return 0; 02420 } 02421 02422 static int TaskContext_getAttribute(lua_State *L) 02423 { 02424 const char *name; 02425 AttributeBase *prop; 02426 02427 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02428 name = luaL_checkstring(L, 2); 02429 02430 prop = tc->getAttribute(name); 02431 02432 if(!prop) 02433 luaL_error(L, "%s failed. No such Attribute", __FILE__); 02434 02435 Attribute_push(L, prop); 02436 return 1; 02437 } 02438 02439 02440 static int TaskContext_getAttributeNames(lua_State *L) 02441 { 02442 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02443 std::vector<std::string> plist = tc->attributes()->getAttributeNames(); 02444 push_vect_str(L, plist); 02445 return 1; 02446 } 02447 02448 static int TaskContext_getAttributes(lua_State *L) 02449 { 02450 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02451 vector<AttributeBase*> props = tc->attributes()->getValues(); 02452 02453 int key = 1; 02454 lua_createtable(L, props.size(), 0); 02455 for(vector<AttributeBase*>::iterator it = props.begin(); it != props.end(); ++it) { 02456 Attribute_push(L, *it); 02457 lua_rawseti(L, -2, key++); 02458 } 02459 02460 return 1; 02461 } 02462 02463 static int TaskContext_removeAttribute(lua_State *L) 02464 { 02465 const char *name; 02466 AttributeBase *prop; 02467 02468 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02469 name = luaL_checkstring(L, 2); 02470 02471 if(!tc->attributes()->hasAttribute(name)) 02472 luaL_error(L, "%s failed. No such attribute", __FILE__); 02473 02474 tc->attributes()->removeAttribute(name); 02475 02476 return 0; 02477 } 02478 02479 static int TaskContext_getOps(lua_State *L) 02480 { 02481 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02482 std::vector<std::string> oplst = tc->operations()->getNames(); 02483 push_vect_str(L, oplst); 02484 return 1; 02485 } 02486 02487 /* returns restype, arity, table-of-arg-descr */ 02488 static int TaskContext_getOpInfo(lua_State *L) 02489 { 02490 int i=1; 02491 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02492 const char *op = luaL_checkstring(L, 2); 02493 std::vector<ArgumentDescription> args; 02494 02495 if(!tc->operations()->hasMember(op)) 02496 luaL_error(L, "TaskContext.getOpInfo failed: no such operation"); 02497 02498 lua_pushstring(L, tc->operations()->getResultType(op).c_str()); /* result type */ 02499 lua_pushinteger(L, tc->operations()->getArity(op)); /* arity */ 02500 lua_pushstring(L, tc->operations()->getDescription(op).c_str()); /* description */ 02501 02502 args = tc->operations()->getArgumentList(op); 02503 02504 lua_newtable(L); 02505 02506 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) { 02507 lua_newtable(L); 02508 lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3); 02509 lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3); 02510 lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3); 02511 lua_rawseti(L, -2, i++); 02512 } 02513 02514 return 4; 02515 } 02516 02517 static int TaskContext_provides(lua_State *L) 02518 { 02519 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02520 Service::shared_ptr srv = tc->provides(); 02521 02522 if(srv == 0) 02523 luaL_error(L, "TaskContext.provides: no default service"); 02524 02525 /* forward to Serivce.provides */ 02526 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv); 02527 lua_replace(L, 1); 02528 return Service_provides(L); 02529 } 02530 02531 static int TaskContext_getProviderNames(lua_State *L) 02532 { 02533 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02534 Service::shared_ptr srv = tc->provides(); 02535 push_vect_str(L, srv->getProviderNames()); 02536 return 1; 02537 } 02538 02539 static int TaskContext_requires(lua_State *L) 02540 { 02541 ServiceRequester::shared_ptr sr; 02542 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02543 sr = tc->requires(); 02544 02545 if(!sr) 02546 luaL_error(L, "TaskContext.requires returned NULL"); 02547 02548 ServiceRequester_push(L, sr.get()); 02549 lua_replace(L, 1); 02550 return ServiceRequester_requires(L); 02551 } 02552 02553 static int TaskContext_connectServices(lua_State *L) 02554 { 02555 int ret; 02556 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02557 TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext)); 02558 ret = tc->connectServices(peer); 02559 lua_pushboolean(L, ret); 02560 return 1; 02561 } 02562 02563 static int TaskContext_hasOperation(lua_State *L) 02564 { 02565 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02566 Service::shared_ptr srv = tc->provides(); 02567 02568 if(srv == 0) 02569 luaL_error(L, "TaskContext.provides: no default service"); 02570 02571 /* forward to Serivce.hasOperation */ 02572 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv); 02573 lua_replace(L, 1); 02574 return Service_hasOperation(L); 02575 } 02576 02577 02578 static int TaskContext_getOperation(lua_State *L) 02579 { 02580 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02581 Service::shared_ptr srv = tc->provides(); 02582 02583 if(srv == 0) 02584 luaL_error(L, "TaskContext.getOperation: no default service"); 02585 02586 /* forward to Serivce.getOperation */ 02587 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv); 02588 lua_replace(L, 1); 02589 return Service_getOperation(L); 02590 } 02591 02592 /* 02593 * SendHandle (required for send) 02594 */ 02595 02596 static void SendStatus_push(lua_State *L, SendStatus ss) 02597 { 02598 switch (ss) { 02599 case SendSuccess: lua_pushstring(L, "SendSuccess"); break; 02600 case SendNotReady: lua_pushstring(L, "SendNotReady"); break; 02601 case SendFailure: lua_pushstring(L, "SendFailure"); break; 02602 default: lua_pushstring(L, "unkown"); 02603 } 02604 } 02605 02606 static int __SendHandle_collect(lua_State *L, bool block) 02607 { 02608 unsigned int coll_argc; 02609 std::vector<DataSourceBase::shared_ptr> coll_args; /* temporarily store args */ 02610 SendStatus ss; 02611 const types::TypeInfo *ti; 02612 OperationInterfacePart *oip; 02613 DataSourceBase::shared_ptr dsb, *dsbp; 02614 02615 unsigned int argc = lua_gettop(L); 02616 SendHandleC *shc = luaM_checkudata_mt(L, 1, "SendHandle", SendHandleC); 02617 02618 /* get orp pointer */ 02619 oip = shc->getOrp(); 02620 coll_argc = oip->collectArity(); 02621 02622 if(argc == 1) { 02623 // No args supplied, create them. 02624 for(unsigned int i=1; i<=coll_argc; i++) { 02625 ti = oip->getCollectType(i); 02626 dsb = ti->buildValue(); 02627 coll_args.push_back(dsb); 02628 shc->arg(dsb); 02629 } 02630 } else if (argc-1 == coll_argc) { 02631 // args supplied, use them. 02632 for(unsigned int arg=2; arg<=argc; arg++) { 02633 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) 02634 dsb = *dsbp; 02635 else 02636 luaL_error(L, "SendHandle.collect: expected Variable argument at position %d", arg-1); 02637 shc->arg(dsb); 02638 } 02639 } else { 02640 luaL_error(L, "SendHandle.collect: wrong number of args. expected either 0 or %d, got %d", 02641 coll_argc, argc-1); 02642 } 02643 02644 if(block) ss = shc->collect(); 02645 else ss = shc->collectIfDone(); 02646 02647 SendStatus_push(L, ss); 02648 02649 if(ss == SendSuccess) { 02650 for (unsigned int i=0; i<coll_args.size(); i++) 02651 Variable_push_coerce(L, coll_args[i]); 02652 } 02653 /* SendStatus + collect args */ 02654 return coll_args.size() + 1; 02655 } 02656 02657 static int SendHandle_collect(lua_State *L) { return __SendHandle_collect(L, true); } 02658 static int SendHandle_collectIfDone(lua_State *L) { return __SendHandle_collect(L, false); } 02659 02660 static const struct luaL_Reg SendHandle_f [] = { 02661 { "collect", SendHandle_collect }, 02662 { "collectIfDone", SendHandle_collectIfDone }, 02663 { NULL, NULL } 02664 }; 02665 02666 static const struct luaL_Reg SendHandle_m [] = { 02667 { "collect", SendHandle_collect }, 02668 { "collectIfDone", SendHandle_collectIfDone }, 02669 { "__gc", GCMethod<SendHandleC> }, 02670 { NULL, NULL } 02671 }; 02672 02673 /* only explicit destruction allowed */ 02674 static int TaskContext_del(lua_State *L) 02675 { 02676 TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext)); 02677 delete tc; 02678 02679 /* this prevents calling rtt methods which would cause a crash */ 02680 luaL_getmetatable(L, "__dead__"); 02681 lua_setmetatable(L, -2); 02682 return 0; 02683 } 02684 02685 static const struct luaL_Reg TaskContext_f [] = { 02686 { "getName", TaskContext_getName }, 02687 { "start", TaskContext_start }, 02688 { "stop", TaskContext_stop }, 02689 { "configure", TaskContext_configure }, 02690 { "activate", TaskContext_activate }, 02691 { "cleanup", TaskContext_cleanup }, 02692 { "error", TaskContext_error }, 02693 { "recover", TaskContext_recover }, 02694 { "getState", TaskContext_getState }, 02695 { "getPeers", TaskContext_getPeers }, 02696 { "addPeer", TaskContext_addPeer }, 02697 { "removePeer", TaskContext_removePeer }, 02698 { "getPeer", TaskContext_getPeer }, 02699 { "getPortNames", TaskContext_getPortNames }, 02700 { "addPort", TaskContext_addPort }, 02701 { "addEventPort", TaskContext_addEventPort }, 02702 { "getPort", TaskContext_getPort }, 02703 { "removePort", TaskContext_removePort }, 02704 { "addProperty", TaskContext_addProperty }, 02705 { "getProperty", TaskContext_getProperty }, 02706 { "getProperties", TaskContext_getProperties }, 02707 { "getPropertyNames", TaskContext_getPropertyNames }, 02708 { "removeProperty", TaskContext_removeProperty }, 02709 { "addAttribute", TaskContext_addAttribute }, 02710 { "getAttribute", TaskContext_getAttribute }, 02711 { "getAttributes", TaskContext_getAttributes }, 02712 { "getAttributeNames", TaskContext_getAttributeNames }, 02713 { "removeAttribute", TaskContext_removeAttribute }, 02714 { "getOps", TaskContext_getOps }, 02715 { "getOpInfo", TaskContext_getOpInfo }, 02716 { "hasOperation", TaskContext_hasOperation }, 02717 { "provides", TaskContext_provides }, 02718 { "getProviderNames", TaskContext_getProviderNames }, 02719 { "connectServices", TaskContext_connectServices }, 02720 { "getOperation", TaskContext_getOperation }, 02721 { "delete", TaskContext_del }, 02722 { NULL, NULL} 02723 }; 02724 02725 static const struct luaL_Reg TaskContext_m [] = { 02726 { "getName", TaskContext_getName }, 02727 { "start", TaskContext_start }, 02728 { "stop", TaskContext_stop }, 02729 { "configure", TaskContext_configure }, 02730 { "activate", TaskContext_activate }, 02731 { "cleanup", TaskContext_cleanup }, 02732 { "error", TaskContext_error }, 02733 { "recover", TaskContext_recover }, 02734 { "getState", TaskContext_getState }, 02735 { "getPeers", TaskContext_getPeers }, 02736 { "addPeer", TaskContext_addPeer }, 02737 { "removePeer", TaskContext_removePeer }, 02738 { "getPeer", TaskContext_getPeer }, 02739 { "getPortNames", TaskContext_getPortNames }, 02740 { "addPort", TaskContext_addPort }, 02741 { "addEventPort", TaskContext_addEventPort }, 02742 { "getPort", TaskContext_getPort }, 02743 { "removePort", TaskContext_removePort }, 02744 { "addProperty", TaskContext_addProperty }, 02745 { "getProperty", TaskContext_getProperty }, 02746 { "getProperties", TaskContext_getProperties }, 02747 { "getPropertyNames", TaskContext_getPropertyNames }, 02748 { "addAttribute", TaskContext_addAttribute }, 02749 { "getAttribute", TaskContext_getAttribute }, 02750 { "getAttributes", TaskContext_getAttributes }, 02751 { "getAttributeNames", TaskContext_getAttributeNames }, 02752 { "removeAttribute", TaskContext_removeAttribute }, 02753 { "removeProperty", TaskContext_removeProperty }, 02754 { "getOps", TaskContext_getOps }, 02755 { "getOpInfo", TaskContext_getOpInfo }, 02756 { "hasOperation", TaskContext_hasOperation }, 02757 { "provides", TaskContext_provides }, 02758 { "getProviderNames", TaskContext_getProviderNames }, 02759 { "requires", TaskContext_requires }, 02760 { "connectServices", TaskContext_connectServices }, 02761 { "getOperation", TaskContext_getOperation }, 02762 { "delete", TaskContext_del }, 02763 // { "__index", TaskContext_index }, 02764 /* we don't GC TaskContexts 02765 * { "__gc", GCMethod<TaskContext> }, */ 02766 { NULL, NULL} 02767 }; 02768 02769 /* 02770 * Execution engine hook registration 02771 */ 02772 02773 /* executable IF */ 02774 class EEHook : public base::ExecutableInterface 02775 { 02776 protected: 02777 std::string func; 02778 lua_State *L; 02779 TaskContext *tc; /* remember this to be able to print TC name 02780 in error messages */ 02781 public: 02782 EEHook(lua_State *_L, std::string _func) { L = _L; func = _func; tc = __getTC(L); } 02783 bool execute() { return call_func(L, func.c_str(), tc, 1, 1); } 02784 }; 02785 02786 static int EEHook_new(lua_State *L) 02787 { 02788 const char *func; 02789 func = luaL_checkstring(L, 1); 02790 luaM_pushobject(L, EEHook)(L, func); 02791 return 1; 02792 } 02793 02794 static int EEHook_enable(lua_State *L) 02795 { 02796 EEHook *eeh = luaM_checkudata(L, 1, EEHook); 02797 TaskContext *tc = __getTC(L); 02798 lua_pushboolean(L, tc->engine()->runFunction(eeh)); 02799 return 1; 02800 } 02801 02802 static int EEHook_disable(lua_State *L) 02803 { EEHook *eeh = luaM_checkudata(L, 1, EEHook); 02804 TaskContext *tc = __getTC(L); 02805 lua_pushboolean(L, tc->engine()->removeFunction(eeh)); 02806 return 1; 02807 } 02808 02809 #if 0 02810 static int EEHook_gc(lua_State *L) 02811 { 02812 EEHook_disable(L); 02813 lua_settop(L, 1); 02814 reinterpret_cast<EEHook*>(lua_touserdata(L, 1))->~EEHook(); 02815 return 0; 02816 } 02817 #endif 02818 02819 static const struct luaL_Reg EEHook_f [] = { 02820 { "new", EEHook_new }, 02821 { "enable", EEHook_enable }, 02822 { "disable", EEHook_disable }, 02823 }; 02824 02825 02826 static const struct luaL_Reg EEHook_m [] = { 02827 { "enable", EEHook_enable }, 02828 { "disable", EEHook_disable }, 02829 /* { "__gc", EEHook_gc }, */ 02830 }; 02831 02832 02833 /* 02834 * Logger and miscellaneous 02835 */ 02836 static const char *const loglevels[] = { 02837 "Never", "Fatal", "Critical", "Error", "Warning", "Info", "Debug", "RealTime", NULL 02838 }; 02839 02840 static int Logger_setLogLevel(lua_State *L) 02841 { 02842 Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels); 02843 log().setLogLevel(ll); 02844 return 0; 02845 } 02846 02847 static int Logger_getLogLevel(lua_State *L) 02848 { 02849 Logger::LogLevel ll = log().getLogLevel(); 02850 02851 switch(ll) { 02852 case Logger::Never: lua_pushstring(L, "Never"); break; 02853 case Logger::Fatal: lua_pushstring(L, "Fatal"); break; 02854 case Logger::Critical: lua_pushstring(L, "Critical"); break; 02855 case Logger::Error: lua_pushstring(L, "Error"); break; 02856 case Logger::Warning: lua_pushstring(L, "Warning"); break; 02857 case Logger::Info: lua_pushstring(L, "Info"); break; 02858 case Logger::Debug: lua_pushstring(L, "Debug"); break; 02859 case Logger::RealTime: lua_pushstring(L, "RealTime"); break; 02860 default: 02861 lua_pushstring(L, "unknown"); 02862 } 02863 return 1; 02864 } 02865 02866 static int Logger_log(lua_State *L) 02867 { 02868 const char *mes; 02869 for(int i=1; i<=lua_gettop(L); i++) { 02870 mes = luaL_checkstring(L, i); 02871 Logger::log() << mes; 02872 } 02873 Logger::log() << endlog(); 02874 return 0; 02875 } 02876 02877 static int Logger_logl(lua_State *L) 02878 { 02879 const char *mes; 02880 Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels); 02881 for(int i=2; i<=lua_gettop(L); i++) { 02882 mes = luaL_checkstring(L, i); 02883 Logger::log(ll) << mes; 02884 } 02885 Logger::log(ll) << endlog(); 02886 return 0; 02887 } 02888 02889 /* misc stuff */ 02890 02891 static int getTime(lua_State *L) 02892 { 02893 unsigned long nsec, sec; 02894 RTT::os::TimeService::nsecs total_nsec = TimeService::Instance()->getNSecs(); 02895 sec = total_nsec / 1000000000; 02896 nsec = total_nsec % 1000000000; 02897 lua_pushinteger(L, sec); 02898 lua_pushinteger(L, nsec); 02899 return 2; 02900 } 02901 02902 static int rtt_sleep(lua_State *L) 02903 { 02904 TIME_SPEC ts; 02905 ts.tv_sec = luaL_checknumber(L, 1); 02906 ts.tv_nsec = luaL_checknumber(L, 2); 02907 rtos_nanosleep(&ts, NULL); 02908 return 0; 02909 } 02910 02911 static int getTC(lua_State *L) 02912 { 02913 lua_pushstring(L, "this_TC"); 02914 lua_rawget(L, LUA_REGISTRYINDEX); 02915 return 1; 02916 } 02917 02918 static TaskContext* __getTC(lua_State *L) 02919 { 02920 TaskContext *tc; 02921 getTC(L); 02922 tc = *(luaM_checkudata_bx(L, -1, TaskContext)); 02923 lua_pop(L, 1); 02924 return tc; 02925 } 02926 02927 /* access to the globals repository */ 02928 static int globals_getNames(lua_State *L) 02929 { 02930 GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance(); 02931 push_vect_str(L, gr->getAttributeNames() ); 02932 return 1; 02933 } 02934 02935 static int globals_get(lua_State *L) 02936 { 02937 const char *name; 02938 base::AttributeBase *ab; 02939 DataSourceBase::shared_ptr dsb; 02940 02941 name = luaL_checkstring(L, 1); 02942 GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance(); 02943 02944 ab = gr->getAttribute(name); 02945 02946 if (ab) 02947 Variable_push_coerce(L, ab->getDataSource()); 02948 else 02949 lua_pushnil(L); 02950 02951 return 1; 02952 } 02953 02954 /* global service */ 02955 static int provides_global(lua_State *L) 02956 { 02957 luaM_pushobject_mt(L, "Service", Service::shared_ptr)(GlobalService::Instance()); 02958 lua_insert(L, 1); 02959 return Service_provides(L); 02960 } 02961 02962 static int rtt_services(lua_State *L) 02963 { 02964 push_vect_str(L, PluginLoader::Instance()->listServices()); 02965 return 1; 02966 } 02967 02968 static int rtt_typekits(lua_State *L) 02969 { 02970 push_vect_str(L, PluginLoader::Instance()->listTypekits()); 02971 return 1; 02972 } 02973 02974 static int rtt_types(lua_State *L) 02975 { 02976 push_vect_str(L, TypeInfoRepository::Instance()->getTypes()); 02977 return 1; 02978 } 02979 02980 static const struct luaL_Reg rtt_f [] = { 02981 {"getTime", getTime }, 02982 {"sleep", rtt_sleep }, 02983 {"getTC", getTC }, 02984 {"globals_getNames", globals_getNames }, 02985 {"globals_get", globals_get }, 02986 {"provides", provides_global }, 02987 {"services", rtt_services }, 02988 {"typekits", rtt_typekits }, 02989 {"types", rtt_types }, 02990 {"setLogLevel", Logger_setLogLevel }, 02991 {"getLogLevel", Logger_getLogLevel }, 02992 {"log", Logger_log }, 02993 {"logl", Logger_logl }, 02994 {NULL, NULL} 02995 }; 02996 02997 extern "C" int luaopen_rtt(lua_State *L); 02998 02999 int luaopen_rtt(lua_State *L) 03000 { 03001 lua_newtable(L); 03002 lua_replace(L, LUA_ENVIRONINDEX); 03003 03004 luaL_newmetatable(L, "__dead__"); 03005 03006 /* register MyObj 03007 * 1. line creates metatable MyObj and registers name in registry 03008 * 2. line duplicates metatable 03009 * 3. line sets metatable[__index]=metatable 03010 * (more precisely: table at -2 [__index] = top_of_stack, pops top of stack) 03011 * 4. line register methods in metatable 03012 * 5. line registers free functions in global mystuff.MyObj table 03013 */ 03014 luaL_newmetatable(L, "TaskContext"); 03015 lua_pushvalue(L, -1); /* duplicates metatable */ 03016 lua_setfield(L, -2, "__index"); 03017 luaL_register(L, NULL, TaskContext_m); 03018 luaL_register(L, "rtt.TaskContext", TaskContext_f); 03019 03020 luaL_newmetatable(L, "Operation"); 03021 lua_pushvalue(L, -1); 03022 lua_setfield(L, -2, "__index"); 03023 luaL_register(L, NULL, Operation_m); 03024 luaL_register(L, "rtt.Operation", Operation_f); 03025 03026 luaL_newmetatable(L, "Service"); 03027 lua_pushvalue(L, -1); 03028 lua_setfield(L, -2, "__index"); 03029 luaL_register(L, NULL, Service_m); 03030 luaL_register(L, "rtt.Service", Service_f); 03031 03032 luaL_newmetatable(L, "ServiceRequester"); 03033 lua_pushvalue(L, -1); 03034 lua_setfield(L, -2, "__index"); 03035 luaL_register(L, NULL, ServiceRequester_m); 03036 luaL_register(L, "rtt.ServiceRequester", ServiceRequester_f); 03037 03038 luaL_newmetatable(L, "SendHandle"); 03039 lua_pushvalue(L, -1); /* duplicates metatable */ 03040 lua_setfield(L, -2, "__index"); 03041 luaL_register(L, NULL, SendHandle_m); 03042 luaL_register(L, "rtt.SendHandle", SendHandle_f); 03043 03044 luaL_newmetatable(L, "InputPort"); 03045 lua_pushvalue(L, -1); /* duplicates metatable */ 03046 lua_setfield(L, -2, "__index"); 03047 luaL_register(L, NULL, InputPort_m); 03048 luaL_register(L, "rtt.InputPort", InputPort_f); 03049 03050 luaL_newmetatable(L, "OutputPort"); 03051 lua_pushvalue(L, -1); /* duplicates metatable */ 03052 lua_setfield(L, -2, "__index"); 03053 luaL_register(L, NULL, OutputPort_m); 03054 luaL_register(L, "rtt.OutputPort", OutputPort_f); 03055 03056 luaL_newmetatable(L, "Variable"); 03057 lua_pushvalue(L, -1); /* duplicates metatable */ 03058 lua_setfield(L, -2, "__index"); 03059 luaL_register(L, NULL, Variable_m); 03060 luaL_register(L, "rtt.Variable", Variable_f); 03061 03062 luaL_newmetatable(L, "Property"); 03063 lua_pushvalue(L, -1); /* duplicates metatable */ 03064 lua_setfield(L, -2, "__index"); 03065 luaL_register(L, NULL, Property_m); 03066 luaL_register(L, "rtt.Property", Property_f); 03067 03068 luaL_newmetatable(L, "Attribute"); 03069 lua_pushvalue(L, -1); /* duplicates metatable */ 03070 lua_setfield(L, -2, "__index"); 03071 luaL_register(L, NULL, Attribute_m); 03072 luaL_register(L, "rtt.Attribute", Attribute_f); 03073 03074 luaL_newmetatable(L, "EEHook"); 03075 lua_pushvalue(L, -1); /* duplicates metatable */ 03076 lua_setfield(L, -2, "__index"); 03077 luaL_register(L, NULL, EEHook_m); 03078 luaL_register(L, "rtt.EEHook", EEHook_f); 03079 03080 /* misc toplevel functions */ 03081 luaL_register(L, "rtt", rtt_f); 03082 03083 return 1; 03084 } 03085 03086 /* store the TC to be returned by getTC() in registry */ 03087 int set_context_tc(TaskContext *tc, lua_State *L) 03088 { 03089 TaskContext **new_tc; 03090 lua_pushstring(L, "this_TC"); 03091 new_tc = (TaskContext**) lua_newuserdata(L, sizeof(TaskContext*)); 03092 *new_tc = (TaskContext*) tc; 03093 luaL_getmetatable(L, "TaskContext"); 03094 lua_setmetatable(L, -2); 03095 lua_rawset(L, LUA_REGISTRYINDEX); 03096 return 0; 03097 } 03098 03099 03100 /* call a zero arity function with a boolean return value 03101 * used to call various hooks */ 03102 bool call_func(lua_State *L, const char *fname, TaskContext *tc, 03103 int require_function, int require_result) 03104 { 03105 bool ret = true; 03106 int num_res = (require_result != 0) ? 1 : 0; 03107 lua_getglobal(L, fname); 03108 03109 if(lua_isnil(L, -1)) { 03110 lua_pop(L, 1); 03111 if(require_function) 03112 luaL_error(L, "%s: no (required) Lua function %s", tc->getName().c_str(), fname); 03113 else 03114 goto out; 03115 } 03116 03117 if (lua_pcall(L, 0, num_res, 0) != 0) { 03118 Logger::log(Logger::Error) << "LuaComponent '"<< tc->getName() <<"': error calling function " 03119 << fname << ": " << lua_tostring(L, -1) << endlog(); 03120 ret = false; 03121 goto out; 03122 } 03123 03124 if(require_result) { 03125 if (!lua_isboolean(L, -1)) { 03126 Logger::log(Logger::Error) << "LuaComponent '" << tc->getName() << "': " << fname 03127 << " must return a bool but returned a " 03128 << lua_typename(L, lua_type(L, -1)) << endlog(); 03129 ret = false; 03130 goto out; 03131 } 03132 ret = lua_toboolean(L, -1); 03133 lua_pop(L, 1); /* pop result */ 03134 } 03135 out: 03136 return ret; 03137 }