diff --git a/Makefile b/Makefile index 7503b4c..a741750 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ SOLINK := core.so CC = g++ CXX = $(CC) -CFLAGS = -shared -fpic -D_REENTRANT -DVERSION=\"$(VERSION)\" -I$(LUT_INCLUDE) +CFLAGS = -shared -fpic -D_REENTRANT -DVERSION=\"$(VERSION)\" -I$(LUT_INCLUDE) -Wl,--no-undefined CFLAGS += $(shell pkg-config --cflags tango lua$(LUA_VERSION)) LDFLAGS = $(shell pkg-config --libs tango lua$(LUA_VERSION)) CPPFLAGS += $(CFLAGS) diff --git a/src/core/lua/stack.cpp b/src/core/lua/stack.cpp new file mode 100644 index 0000000..7c06ab8 --- /dev/null +++ b/src/core/lua/stack.cpp @@ -0,0 +1,21 @@ +#include "stack.h" + +void push_bool_table(lua_State* L, std::vector v) +{ + lua_newtable(L); + for(int i = 0; i < v.size(); i++) + { + lua_pushboolean(L, v[i]); + lua_rawseti(L, -2, i+1); + } +} + +void push_string_table(lua_State* L, std::vector v) +{ + lua_newtable(L); + for(int i = 0; i < v.size(); i++) + { + lua_pushstring(L, v[i].c_str()); + lua_rawseti(L, -2, i+1); + } +} diff --git a/src/core/lua/stack.h b/src/core/lua/stack.h new file mode 100644 index 0000000..c2cfd6c --- /dev/null +++ b/src/core/lua/stack.h @@ -0,0 +1,32 @@ +#ifndef __STACK_H__ +# define __STACK_H__ + +#include +#include + +#include +#include + +void push_bool_table(lua_State* L, std::vector value); +void push_string_table(lua_State* L, std::vector value); + +// CPP: non-specialized templates must be implemented in header file +template +void push_number_table(lua_State* L, std::vector v) +{ + lua_newtable(L); + for(int i = 0; i < v.size(); i++) + { + lua_pushnumber(L, v[i]); + lua_rawseti(L, -2, i+1); + } +} + +template +T pop_number(lua_State* L, int idx) +{ + LUT_LOG(TRACE, "Popping number value from stack"); + return (T)luaL_checknumber(L, idx); +} + +#endif /* __STACK_H__ */ diff --git a/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp b/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp index a0c8689..df7534d 100644 --- a/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp +++ b/src/core/tango/DeviceProxy/lut_DeviceProxy.cpp @@ -11,6 +11,29 @@ DeviceProxyWrapper::~DeviceProxyWrapper() delete dev; } +// COMMAND WRAPPER ------------------------------------------------------------ +int cmd_wrapper(lua_State* L) +{ + DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lua_touserdata(L, lua_upvalueindex(1)); + const char* name = lua_tostring(L, lua_upvalueindex(2)); + LUT_LOG(TRACE, "Running command wrapper %s/%s()", udata->dev->name().c_str(), name); + + if(udata->cmd_info.find(name) == udata->cmd_info.end()) + { + LUT_LOG(TRACE, "Command info for %s doesn't exist, fetching first", name); + udata->cmd_info[name] = udata->dev->get_command_config(name); + } + long in_type = udata->cmd_info[name].in_type; + long out_type = udata->cmd_info[name].out_type; + + LUT_LOG(TRACE, "Command: %s in:%d out:%d", name, in_type, out_type); + + Tango::DeviceData in = pack_cmd_data(L, 2, in_type); + Tango::DeviceData out = udata->dev->command_inout(name, in); + unpack_cmd_data(L, out, out_type); + return 1; +} + // TANGO API ------------------------------------------------------------------ int lut_DeviceProxy_status(lua_State* L) { @@ -24,13 +47,29 @@ int lut_DeviceProxy_get_attribute_list(lua_State* L) { LUT_LOG(TRACE, "TANGO API DeviceProxy:get_attribute_list()"); DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); - vector* attrlist = udata->dev->get_attribute_list(); + std::vector* attrlist = udata->dev->get_attribute_list(); lua_newtable(L); for(int i = 0; i < attrlist->size(); i++) { lua_pushstring(L, (*attrlist)[i].c_str()); lua_rawseti(L, -2, i+1); } + delete attrlist; + return 1; +} + +int lut_DeviceProxy_get_command_list(lua_State* L) +{ + LUT_LOG(TRACE, "TANGO API DeviceProxy:get_command_list()"); + DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); + std::vector* cmdlist = udata->dev->get_command_list(); + lua_newtable(L); + for(int i = 0; i < cmdlist->size(); i++) + { + lua_pushstring(L, (*cmdlist)[i].c_str()); + lua_rawseti(L, -2, i+1); + } + delete cmdlist; return 1; } @@ -71,21 +110,34 @@ int lut_DeviceProxy_destroy(lua_State* L) return 0; } -// aka read_attribute +// aka read_attribute / run command int lut_DeviceProxy_index(lua_State* L) { DeviceProxyWrapper* udata = (DeviceProxyWrapper*)lut_getobj(L, 1); - const char* attr_name = luaL_checkstring(L, 2); + const char* name = luaL_checkstring(L, 2); - LUT_LOG(TRACE, "LUA API DeviceProxy:index(%s)", attr_name); - - Tango::DeviceAttribute attr = udata->dev->read_attribute(attr_name); - - udata->type_map[attr_name].type = attr.get_type(); - udata->type_map[attr_name].format = attr.get_data_format(); - - extract_and_push(L, attr); + LUT_LOG(TRACE, "LUA API DeviceProxy:index(%s)", name); + std::vector* cmdlist = udata->dev->get_command_list(); + if(std::count(cmdlist->begin(), cmdlist->end(), name)) + { + // index is a command, push wrapper closure + // commands are supposed to be called, to allow this + // command "read" returns a function closure + lua_pushlightuserdata(L, udata); + lua_pushstring(L, name); + lua_pushcclosure(L, cmd_wrapper, 2); + } + else + { + // index is an attribute + LUT_LOG(TRACE, "Reading attribute %s", name); + Tango::DeviceAttribute attr = udata->dev->read_attribute(name); + udata->type_map[name].type = attr.get_type(); + udata->type_map[name].format = attr.get_data_format(); + unpack_attr_data(L, attr); + } + delete cmdlist; return 1; } @@ -97,16 +149,25 @@ int lut_DeviceProxy_newindex(lua_State* L) LUT_LOG(TRACE, "LUA API DeviceProxy:newindex(%s)", attr_name); + std::vector* attrlist = udata->dev->get_attribute_list(); + if(!std::count(attrlist->begin(), attrlist->end(), attr_name)) + { + // name is not an attribute + LUT_LOG(ERROR, "Not an attribute: %s", attr_name); + return 0; + } + if(udata->type_map.find(attr_name) == udata->type_map.end()) { + // no cached type mapping LUT_LOG(TRACE, "Type mapping for attribute %s doesn't exist, reading first", attr_name); Tango::DeviceAttribute attr = udata->dev->read_attribute(attr_name); udata->type_map[attr_name].type = attr.get_type(); udata->type_map[attr_name].format = attr.get_data_format(); } - Tango::DeviceAttribute v = pop_and_pack(L, udata->type_map[attr_name], attr_name); + Tango::DeviceAttribute v = pack_attr_data(L, udata->type_map[attr_name], attr_name); udata->dev->write_attribute(v); - return 1; + return 0; } diff --git a/src/core/tango/DeviceProxy/lut_DeviceProxy.h b/src/core/tango/DeviceProxy/lut_DeviceProxy.h index fcc9cd1..8cf2ee9 100644 --- a/src/core/tango/DeviceProxy/lut_DeviceProxy.h +++ b/src/core/tango/DeviceProxy/lut_DeviceProxy.h @@ -1,6 +1,9 @@ #ifndef __LUT_DEVICEPROXY_H__ # define __LUT_DEVICEPROXY_H__ +#include +#include + #include #include @@ -8,6 +11,7 @@ #include #include +#include #define LUT_DEVICEPROXY "lut_DeviceProxy" @@ -19,11 +23,17 @@ class DeviceProxyWrapper ~DeviceProxyWrapper(); Tango::DeviceProxy* dev; AttrTypeMap type_map; + CmdInfoMap cmd_info; }; +// Command wrapper +int cmd_wrapper(lua_State* L); + // Tango API int lut_DeviceProxy_status(lua_State* L); int lut_DeviceProxy_get_attribute_list(lua_State* L); +int lut_DeviceProxy_get_command_list(lua_State* L); +int lut_DeviceProxy_command_wrapper(lua_State* L); // Lua API void lut_lua_register_DeviceProxy(lua_State* L); @@ -41,7 +51,8 @@ static const luaL_reg lut_DeviceProxy[] = // Tango API { "status", lut_DeviceProxy_status }, - { "get_attribute_list", lut_DeviceProxy_get_attribute_list}, + { "get_attribute_list", lut_DeviceProxy_get_attribute_list }, + { "get_command_list", lut_DeviceProxy_get_command_list }, { NULL, NULL } }; diff --git a/src/core/tango/attrdata.cpp b/src/core/tango/attrdata.cpp index 5ea5bb0..2197c53 100644 --- a/src/core/tango/attrdata.cpp +++ b/src/core/tango/attrdata.cpp @@ -1,6 +1,6 @@ #include "attrdata.h" -void extract_and_push(lua_State* L, Tango::DeviceAttribute attr) +void unpack_attr_data(lua_State* L, Tango::DeviceAttribute attr) { switch(attr.get_type()) { @@ -9,37 +9,37 @@ void extract_and_push(lua_State* L, Tango::DeviceAttribute attr) break; case 1: // bool - push_bool(L, attr); + push_attr_bool(L, attr); break; case 2: // short - push_number(L, attr); + push_attr_number(L, attr); break; case 3: // long - push_number(L, attr); + push_attr_number(L, attr); break; case 4: // float - push_number(L, attr); + push_attr_number(L, attr); break; case 5: // double - push_number(L, attr); + push_attr_number(L, attr); break; case 6: // ushort - push_number(L, attr); + push_attr_number(L, attr); break; case 7: // ulong - push_number(L, attr); + push_attr_number(L, attr); break; case 8: // string case 9: // char[] case 20: // const string - push_string(L, attr); + push_attr_string(L, attr); break; case 10: // short[] @@ -115,11 +115,11 @@ void extract_and_push(lua_State* L, Tango::DeviceAttribute attr) } case 23: // long64 - push_number(L, attr); + push_attr_number(L, attr); break; case 24: // ulong64 - push_number(L, attr); + push_attr_number(L, attr); break; case 25: // long64[] @@ -139,7 +139,7 @@ void extract_and_push(lua_State* L, Tango::DeviceAttribute attr) } case 27: // int - push_number(L, attr); + push_attr_number(L, attr); break; case 17: // longstring[] ??? @@ -158,7 +158,7 @@ void extract_and_push(lua_State* L, Tango::DeviceAttribute attr) } template -void push_number(lua_State* L, Tango::DeviceAttribute attr) +void push_attr_number(lua_State* L, Tango::DeviceAttribute attr) { Tango::AttrDataFormat fmt = attr.get_data_format(); if(fmt == Tango::SCALAR) @@ -188,7 +188,7 @@ void push_number(lua_State* L, Tango::DeviceAttribute attr) } } -void push_bool(lua_State* L, Tango::DeviceAttribute attr) +void push_attr_bool(lua_State* L, Tango::DeviceAttribute attr) { Tango::AttrDataFormat fmt = attr.get_data_format(); if(fmt == Tango::SCALAR) @@ -216,7 +216,7 @@ void push_bool(lua_State* L, Tango::DeviceAttribute attr) } -void push_string(lua_State* L, Tango::DeviceAttribute attr) +void push_attr_string(lua_State* L, Tango::DeviceAttribute attr) { Tango::AttrDataFormat fmt = attr.get_data_format(); if(fmt == Tango::SCALAR) @@ -243,38 +243,7 @@ void push_string(lua_State* L, Tango::DeviceAttribute attr) } } -template -void push_number_table(lua_State* L, std::vector v) -{ - lua_newtable(L); - for(int i = 0; i < v.size(); i++) - { - lua_pushnumber(L, v[i]); - lua_rawseti(L, -2, i+1); - } -} - -void push_bool_table(lua_State* L, std::vector v) -{ - lua_newtable(L); - for(int i = 0; i < v.size(); i++) - { - lua_pushboolean(L, v[i]); - lua_rawseti(L, -2, i+1); - } -} - -void push_string_table(lua_State* L, std::vector v) -{ - lua_newtable(L); - for(int i = 0; i < v.size(); i++) - { - lua_pushstring(L, v[i].c_str()); - lua_rawseti(L, -2, i+1); - } -} - -Tango::DeviceAttribute pop_and_pack(lua_State* L, AttrTypeDescription d, const char* attr_name) +Tango::DeviceAttribute pack_attr_data(lua_State* L, AttrTypeDescription d, const char* attr_name) { switch(d.type) { @@ -284,49 +253,49 @@ Tango::DeviceAttribute pop_and_pack(lua_State* L, AttrTypeDescription d, const c case 1: // bool // Lua 5.1 is missing the luaL_checkboolean function - return pack_value(attr_name, (bool)lua_toboolean(L, 3)); + return pack_attr_value(attr_name, (bool)lua_toboolean(L, 3)); break; case 2: // short - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 3: // long - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 4: // float - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 5: // double - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 6: // ushort - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 7: // ulong - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 8: // string case 9: // char[] case 20: // const string - return pack_value(attr_name, luaL_checkstring(L, 3)); + return pack_attr_value(attr_name, luaL_checkstring(L, 3)); break; case 23: // long64 - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 24: // ulong64 - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 27: // int - return pack_value(attr_name, pop_number(L, 3)); + return pack_attr_value(attr_name, pop_number(L, 3)); break; case 10: // short[] @@ -353,13 +322,7 @@ Tango::DeviceAttribute pop_and_pack(lua_State* L, AttrTypeDescription d, const c } template -T pop_number(lua_State* L, int idx) -{ - return luaL_checknumber(L, idx); -} - -template -Tango::DeviceAttribute pack_value(const char* name, T value) +Tango::DeviceAttribute pack_attr_value(const char* name, T value) { Tango::DeviceAttribute v(name, value); return v; diff --git a/src/core/tango/attrdata.h b/src/core/tango/attrdata.h index 965464d..b5ec40b 100644 --- a/src/core/tango/attrdata.h +++ b/src/core/tango/attrdata.h @@ -1,6 +1,7 @@ #ifndef __ATTRDATA_H__ # define __ATTRDATA_H__ +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include typedef struct { @@ -18,25 +20,17 @@ typedef struct typedef std::map AttrTypeMap; // READ ATTRIBUTE ------------------------------------------------------------- -void extract_and_push(lua_State* L, Tango::DeviceAttribute attr); +void unpack_attr_data(lua_State* L, Tango::DeviceAttribute attr); template -void push_number(lua_State* L, Tango::DeviceAttribute attr); -void push_bool(lua_State* L, Tango::DeviceAttribute attr); -void push_string(lua_State* L, Tango::DeviceAttribute attr); - -template -void push_number_table(lua_State* L, std::vector value); -void push_bool_table(lua_State* L, std::vector value); -void push_string_table(lua_State* L, std::vector value); +void push_attr_number(lua_State* L, Tango::DeviceAttribute attr); +void push_attr_bool(lua_State* L, Tango::DeviceAttribute attr); +void push_attr_string(lua_State* L, Tango::DeviceAttribute attr); // WRITE ATTRIBUTE ------------------------------------------------------------ -Tango::DeviceAttribute pop_and_pack(lua_State* L, AttrTypeDescription d, const char* attr_name); +Tango::DeviceAttribute pack_attr_data(lua_State* L, AttrTypeDescription d, const char* attr_name); template -T pop_number(lua_State* L, int idx); - -template -Tango::DeviceAttribute pack_value(const char* name, T value); +Tango::DeviceAttribute pack_attr_value(const char* name, T value); #endif /* __ATTRDATA_H__ */ diff --git a/src/core/tango/cmddata.cpp b/src/core/tango/cmddata.cpp new file mode 100644 index 0000000..884ea82 --- /dev/null +++ b/src/core/tango/cmddata.cpp @@ -0,0 +1,292 @@ +#include "cmddata.h" + +void unpack_cmd_data(lua_State* L, Tango::DeviceData data, long type) +{ + switch(type) + { + case 0: // void + lua_pushnil(L); + break; + + case 1: // bool + push_cmd_bool(L, data); + break; + + case 2: // short + push_cmd_number(L, data); + break; + + case 3: // long + push_cmd_number(L, data); + break; + + case 4: // float + push_cmd_number(L, data); + break; + + case 5: // double + push_cmd_number(L, data); + break; + + case 6: // ushort + push_cmd_number(L, data); + break; + + case 7: // ulong + push_cmd_number(L, data); + break; + + case 8: // string + case 9: // char[] + case 20: // const string + push_cmd_string(L, data); + break; + + case 10: // short[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 11: // long[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 12: // float[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 13: // double[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 14: // ushort[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 15: // ulong[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 16: // string[] + { + std::vector v; + data >> v; + push_string_table(L, v); + break; + } + + case 21: // bool[] + { + std::vector v; + //data >> v; + push_bool_table(L, v); + break; + } + + case 22: // uchar + { + unsigned char v; + // data >> v; + lua_pushstring(L, (const char *)&v); + break; + } + + case 23: // long64 + push_cmd_number(L, data); + break; + + case 24: // ulong64 + push_cmd_number(L, data); + break; + + case 25: // long64[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 26: // ulong64[] + { + std::vector v; + data >> v; + push_number_table(L, v); + break; + } + + case 27: // int + push_cmd_number(L, data); + break; + + case 17: // longstring[] ??? + case 18: // doublestring[] ??? + case 19: // DevState + case 28: // DevEncoded + LUT_LOG(WARNING, "Command type conversion not implemented yet: %d", type); + lua_pushnil(L); + break; + + default: + LUT_LOG(ERROR, "Unknown type: %d", type); + lua_pushnil(L); + //return luaL_error(L, "Device returned type %d, that is unknown or unsupported.", attr.get_type()); + } +} + +template +void push_cmd_number(lua_State* L, Tango::DeviceData data) +{ + T v; + data >> v; + lua_pushnumber(L, v); +} + +void push_cmd_bool(lua_State* L, Tango::DeviceData data) +{ + bool v; + data >> v; + lua_pushboolean(L, v); + +} + +void push_cmd_string(lua_State* L, Tango::DeviceData data) +{ + std::string v; + data >> v; + lua_pushstring(L, v.c_str()); +} + +Tango::DeviceData pack_cmd_data(lua_State* L, int idx, long type) +{ + Tango::DeviceData data; + switch(type) + { + case 0: // void + break; + + case 1: // bool + { + bool v = lua_toboolean(L, idx); + data << v; + break; + } + + case 2: // short + { + short v = pop_number(L, idx); + data << v; + break; + } + + case 3: // long + { + long v = pop_number(L, idx); + data << v; + break; + } + + case 4: // float + { + float v = pop_number(L, idx); + data << v; + break; + } + + case 5: // double + { + double v = pop_number(L, idx); + data << v; + break; + } + + case 6: // ushort + { + unsigned short v = pop_number(L, idx); + data << v; + break; + } + + case 7: // ulong + { + unsigned long v = pop_number(L, idx); + data << v; + break; + } + + case 8: // string + case 9: // char[] + case 20: // const string + { + const char* v = luaL_checkstring(L, idx); + data << v; + break; + } + + case 23: // long64 + { + // int64_t v = pop_number(L, idx); + // data << v; + break; + } + + case 24: // ulong64 + { + // uint64_t v = pop_number(L, idx); + // data << v; + break; + } + + case 27: // int + { + int v = pop_number(L, idx); + data << v; + break; + } + + case 10: // short[] + case 11: // long[] + case 12: // float[] + case 13: // double[] + case 14: // ushort[] + case 15: // ulong[] + case 16: // string[] + case 17: // longstring[] ??? + case 18: // doublestring[] ??? + case 19: // DevState + case 21: // bool[] + case 22: // uchar + case 25: // long64[] + case 26: // ulong64[] + case 28: // DevEncoded + LUT_LOG(WARNING, "Command input argument type not implemented yet: %d", type); + break; + + default: + LUT_LOG(ERROR, "Command input argument type is unknown: %d", type); + } + return data; +} diff --git a/src/core/tango/cmddata.h b/src/core/tango/cmddata.h new file mode 100644 index 0000000..2cb713c --- /dev/null +++ b/src/core/tango/cmddata.h @@ -0,0 +1,26 @@ +#ifndef __CMDDATA_H__ +# define __CMDDATA_H__ + +#include +#include +#include + +#include +#include +#include +#include + +typedef std::map CmdInfoMap; + +// DATA OUT ------------------------------------------------------------------- +void unpack_cmd_data(lua_State* L, Tango::DeviceData data, long type); + +// DATA IN -------------------------------------------------------------------- +template +void push_cmd_number(lua_State* L, Tango::DeviceData data); +void push_cmd_bool(lua_State* L, Tango::DeviceData data); +void push_cmd_string(lua_State* L, Tango::DeviceData data); + +Tango::DeviceData pack_cmd_data(lua_State* L, int idx, long type); + +#endif /* __CMDDATA_H__ */