luat_lib_vmx.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "luat_base.h"
  2. #include "luat_msgbus.h"
  3. #include "luat_irq.h"
  4. #include "luat_bget.h"
  5. #include "lauxlib.h"
  6. #ifndef LUAT_VMX_COUNT
  7. #define LUAT_VMX_COUNT 4
  8. #endif
  9. #define LUAT_LOG_TAG "vms"
  10. #include "luat_log.h"
  11. typedef struct luat_vmx {
  12. lua_State* L;
  13. char* buff;
  14. luat_bget_t bg;
  15. int lua_ref_id;
  16. }luat_vmx_t;
  17. static luat_vmx_t vms[LUAT_VMX_COUNT];
  18. static void* vms_alloc(void* ud, void *ptr, unsigned int osize, unsigned int nsize) {
  19. if (ud == NULL)
  20. return NULL;
  21. if (nsize)
  22. {
  23. void* ptmp = luat_bgetr((luat_bget_t*)ud, ptr, nsize);
  24. if(ptmp == NULL && osize >= nsize)
  25. {
  26. return ptr;
  27. }
  28. return ptmp;
  29. }
  30. luat_brel((luat_bget_t*)ud, ptr);
  31. return NULL;
  32. }
  33. static const luaL_Reg loadedlibs[] = {
  34. {"_G", luaopen_base}, // _G
  35. //{LUA_LOADLIBNAME, luaopen_package}, // require
  36. {LUA_TABLIBNAME, luaopen_table}, // table库,操作table类型的数据结构
  37. {LUA_IOLIBNAME, luaopen_io}, // io库,操作文件
  38. {LUA_OSLIBNAME, luaopen_os}, // os库,已精简
  39. {LUA_STRLIBNAME, luaopen_string}, // string库,字符串操作
  40. {LUA_MATHLIBNAME, luaopen_math}, // math 数值计算
  41. // {LUA_UTF8LIBNAME, luaopen_utf8},
  42. {LUA_DBLIBNAME, luaopen_debug}, // debug库,已精简
  43. {"rtos", luaopen_rtos}, // rtos底层库, 核心功能是队列和定时器
  44. {"log", luaopen_log}, // 日志库
  45. {"timer", luaopen_timer}, // 延时库
  46. {"pack", luaopen_pack}, // pack.pack/pack.unpack
  47. {"json", luaopen_cjson}, // json
  48. {"zbuff", luaopen_zbuff}, //
  49. {"crypto", luaopen_crypto},
  50. #ifdef LUAT_USE_GPIO
  51. {"gpio", luaopen_gpio},
  52. #endif
  53. #ifdef LUAT_USE_I2C
  54. {"i2c", luaopen_i2c},
  55. #endif
  56. #ifdef LUAT_USE_SPI
  57. {"spi", luaopen_spi},
  58. #endif
  59. #ifdef LUAT_USE_PWM
  60. {"pwm", luaopen_pwm},
  61. #endif
  62. #ifdef LUAT_USE_ADC
  63. {"adc", luaopen_adc},
  64. #endif
  65. #ifdef LUAT_USE_GMSSL
  66. {"gmssl", luaopen_gmssl},
  67. #endif
  68. {NULL, NULL}
  69. };
  70. // 创建虚拟机
  71. static int l_vmx_create(lua_State *L) {
  72. // 寻找空位
  73. int index = -1;
  74. for (size_t i = 0; i < LUAT_VMX_COUNT; i++)
  75. {
  76. if (vms[i].buff == NULL) {
  77. index = i;
  78. break;
  79. }
  80. }
  81. if (index == -1) {
  82. LLOGW("too many Lua VMs");
  83. return 0;
  84. }
  85. // 分配内存
  86. void* buff = lua_newuserdata(L, 32*1024);
  87. if (buff == NULL) {
  88. LLOGD("out of memory");
  89. return 0;
  90. }
  91. int top = lua_gettop(L);
  92. vms[index].buff = buff;
  93. luat_bget_init(&vms[index].bg);
  94. luat_bpool(&vms[index].bg, buff, 32*1024);
  95. // 创建lua_State
  96. vms[index].L = lua_newstate(vms_alloc, &vms[index].bg);
  97. // 加入必要的库
  98. const luaL_Reg *lib;
  99. for (lib = loadedlibs; lib->func; lib++) {
  100. luaL_requiref(vms[index].L, lib->name, lib->func, 1);
  101. lua_pop(vms[index].L, 1); /* remove lib */
  102. }
  103. // 返回结果
  104. if (lua_gettop(L) != top)
  105. lua_settop(L, top);
  106. vms[index].lua_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
  107. lua_pushinteger(L, index);
  108. return 1;
  109. }
  110. // 将值在两个VM之间搬运
  111. static int vm2vm_copy(int index, lua_State *Lsrc, lua_State *Ldst) {
  112. if (lua_isnil(Lsrc, index)) {
  113. lua_pushnil(Ldst);
  114. }
  115. else if (lua_isboolean(Lsrc, index)) {
  116. lua_pushboolean(Ldst, lua_toboolean(Lsrc, index));
  117. }
  118. else if (lua_isinteger(Lsrc, index)) {
  119. lua_pushinteger(Ldst, lua_tointeger(Lsrc, index));
  120. }
  121. else if (lua_isnumber(Lsrc, index)) {
  122. lua_pushnumber(Ldst, lua_tonumber(Lsrc, index));
  123. }
  124. else if (lua_isstring(Lsrc, index)) {
  125. size_t str_len = 0;
  126. const char* tmp = luaL_checklstring(Lsrc, index, &str_len);
  127. lua_pushlstring(Ldst, tmp, str_len);
  128. }
  129. else {
  130. return -1;
  131. }
  132. return 0;
  133. }
  134. // 在指定虚拟机内执行代码
  135. static int l_vmx_exec(lua_State *L) {
  136. int vm_id = luaL_checkinteger(L, 1);
  137. size_t sz = 0;
  138. const char* buff = luaL_checklstring(L, 2, &sz);
  139. if (sz == 0) {
  140. lua_pushboolean(L, 0);
  141. lua_pushliteral(L, "emtry string");
  142. return 2;
  143. }
  144. if (vm_id < 0 || vm_id >= LUAT_VMX_COUNT || vms[vm_id].L == NULL) {
  145. lua_pushboolean(L, 0);
  146. lua_pushliteral(L, "invaild vm id");
  147. return 2;
  148. }
  149. lua_settop(vms[vm_id].L, 0);
  150. int ret = luaL_loadbuffer(vms[vm_id].L, buff, sz, "vmx");
  151. if (ret) {
  152. lua_pushboolean(L, 0);
  153. lua_pushstring(L, lua_tostring(L, -1));
  154. lua_pushinteger(L, ret);
  155. return 3;
  156. }
  157. int top = lua_gettop(L);
  158. if (top > 2) { // 推入参数,仅支持string/数值/bool
  159. for (size_t i = 2; i < top; i++)
  160. {
  161. if (!vm2vm_copy(i+1, L, vms[vm_id].L)) {
  162. lua_settop(vms[vm_id].L, 0);
  163. lua_pushboolean(L, 0);
  164. lua_pushliteral(L, "only bool/number/string is accepted");
  165. lua_pushinteger(L, i+1);
  166. return 3;
  167. }
  168. }
  169. }
  170. ret = lua_pcall(vms[vm_id].L, top - 2, 1, 0);
  171. if (ret) {
  172. lua_pushboolean(L, 0);
  173. lua_pushstring(L, lua_tostring(vms[vm_id].L, -1));
  174. lua_pushinteger(L, ret);
  175. return 3;
  176. }
  177. else if (lua_gettop(vms[vm_id].L) > 0) {
  178. lua_pushboolean(L, 1);
  179. if (vm2vm_copy(1, vms[vm_id].L, L)) {
  180. return 2;
  181. }
  182. else {
  183. return 1;
  184. }
  185. }
  186. lua_pushboolean(L, 1);
  187. return 1;
  188. }
  189. static int l_vmx_bind(lua_State *L) {
  190. return 0;
  191. }
  192. static int l_vmx_close(lua_State *L) {
  193. return 0;
  194. }
  195. static int l_vmx_count(lua_State *L) {
  196. int count = 0;
  197. for (size_t i = 0; i < LUAT_VMX_COUNT; i++)
  198. {
  199. if (vms[i].L)
  200. count++;
  201. }
  202. lua_pushinteger(L, count);
  203. return 1;
  204. }
  205. #include "rotable2.h"
  206. static const rotable_Reg_t reg_vmx[] =
  207. {
  208. { "create" , ROREG_FUNC(l_vmx_create)},
  209. { "bind" , ROREG_FUNC(l_vmx_bind)},
  210. { "exec", ROREG_FUNC(l_vmx_exec)},
  211. { "close" , ROREG_FUNC(l_vmx_close)},
  212. { "count" , ROREG_FUNC(l_vmx_count)},
  213. { NULL, ROREG_INT(0)}
  214. };
  215. LUAMOD_API int luaopen_vmx( lua_State *L ) {
  216. luat_newlib2(L, reg_vmx);
  217. return 1;
  218. }