├── GNUmakefile ├── Makefile ├── README ├── luaproxy-1.2.3-1.rockspec ├── luaproxy.c ├── luaproxy.h ├── shlib_version ├── test-proxy.lua └── vars.lua /GNUmakefile: -------------------------------------------------------------------------------- 1 | -include ../GNUmakefile.inc 2 | 3 | SRCS= luaproxy.c 4 | LIB= proxy 5 | 6 | LUAVER?= $(shell lua -v 2>&1 | cut -c 5-7) 7 | LUAINC?= /usr/include/lua${LUAVER} 8 | 9 | CFLAGS+= -O3 -Wall -fPIC -I/usr/include -I${LUAINC} 10 | LDADD+= -L/usr/lib 11 | 12 | LIBDIR= /usr/lib/lua/${LUAVER} 13 | 14 | ${LIB}.so: ${SRCS:.c=.o} 15 | cc -shared -o ${LIB}.so ${CFLAGS} ${SRCS:.c=.o} ${LDADD} 16 | 17 | clean: 18 | rm -f *.o *.so 19 | install: 20 | install -d ${DESTDIR}${LIBDIR} 21 | install ${LIB}.so ${DESTDIR}${LIBDIR} 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRCS= luaproxy.c 2 | LIB= proxy 3 | 4 | OS!= uname 5 | 6 | .if ${OS} == "NetBSD" 7 | LOCALBASE= /usr/pkg 8 | LDADD+= -R/usr/lib -R${LOCALBASE}/lib 9 | .else 10 | LOCALBASE= /usr/local 11 | .endif 12 | 13 | NOLINT= 1 14 | CFLAGS+= -Wall -I${LOCALBASE}/include 15 | LDADD+= -L${LOCALBASE}/lib 16 | 17 | LIBDIR= ${LOCALBASE}/lib/lua/5.2 18 | 19 | libinstall: 20 | 21 | install: 22 | ${INSTALL} -d ${DESTDIR}${LIBDIR} 23 | ${INSTALL} lib${LIB}.so ${DESTDIR}${LIBDIR}/${LIB}.so 24 | 25 | .include 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | A Lua proxy to access a Lua state from within another state 2 | 3 | Copyright (C) Micro Systems Marc Balmer. 4 | You can reach the author at marc@msys.ch 5 | 6 | Makefile is for BSD systems 7 | GNUmakefile is for Linux systems 8 | -------------------------------------------------------------------------------- /luaproxy-1.2.3-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "luaproxy" 2 | version = "1.2.3-1" 3 | source = { 4 | url = "git://github.com/mbalmer/luaproxy", 5 | tag = "v1.2.3", 6 | } 7 | description = { 8 | summary = "A Lua proxy to access a Lua state from within another state", 9 | detailed = "Access a Lua state from within another state.", 10 | homepage = "http://github.com/mbalmer/luaproxy", 11 | license = "3-clause BSD", 12 | } 13 | dependencies = { 14 | "lua >= 5.1", 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | ["proxy"] = { 20 | sources = "luaproxy.c" 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /luaproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 - 2018, Micro Systems Marc Balmer, CH-5073 Gipf-Oberfrick 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Micro Systems Marc Balmer nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* State proxy for Lua */ 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "luaproxy.h" 40 | 41 | static int proxy_dostring(lua_State *); 42 | static void proxy_unmap(lua_State *L, lua_State *R); 43 | 44 | static int 45 | proxy_clear(lua_State *L) 46 | { 47 | proxy_data *p = luaL_checkudata(L, 1, PROXY_METATABLE); 48 | if (p->close_on_gc) 49 | lua_close(p->L); 50 | return 0; 51 | } 52 | 53 | static int 54 | object_clear(lua_State *L) 55 | { 56 | proxy_object *o = luaL_checkudata(L, 1, OBJECT_METATABLE); 57 | 58 | luaL_unref(o->L, LUA_REGISTRYINDEX, o->ref); 59 | return 0; 60 | } 61 | 62 | static int 63 | proxy_index(lua_State *L) 64 | { 65 | proxy_data *p; 66 | char nam[64]; 67 | 68 | p = luaL_checkudata(L, -2, PROXY_METATABLE); 69 | luaL_argcheck(L, p->L != NULL, -2, "no State data set"); 70 | 71 | if (lua_type(L, -1) == LUA_TNUMBER) 72 | snprintf(nam, sizeof nam, "%d", (int)lua_tonumber(L, -1)); 73 | else 74 | snprintf(nam, sizeof nam, "%s", lua_tostring(L, -1)); 75 | 76 | if (!strcmp(nam, "dostring")) 77 | lua_pushcfunction(L, proxy_dostring); 78 | else { 79 | lua_getglobal(p->L, nam); 80 | proxy_unmap(L, p->L); 81 | } 82 | return 1; 83 | } 84 | 85 | static void 86 | proxy_map(lua_State *L, lua_State *R, int t, int global) 87 | { 88 | int top; 89 | char nam[64]; 90 | 91 | luaL_checkstack(R, 3, "out of stack space"); 92 | switch (lua_type(L, -2)) { 93 | case LUA_TNUMBER: 94 | lua_pushnumber(R, lua_tonumber(L, -2)); 95 | snprintf(nam, sizeof nam, "%d", (int)lua_tonumber(L, -2)); 96 | break; 97 | case LUA_TSTRING: 98 | snprintf(nam, sizeof nam, "%s", lua_tostring(L, -2)); 99 | lua_pushstring(R, lua_tostring(L, -2)); 100 | break; 101 | default: 102 | luaL_error(L, "proxy: data type '%s' is not " 103 | "supported as an index value", luaL_typename(L, -2)); 104 | return; 105 | } 106 | switch (lua_type(L, -1)) { 107 | case LUA_TBOOLEAN: 108 | lua_pushboolean(R, lua_toboolean(L, -1)); 109 | break; 110 | case LUA_TNUMBER: 111 | if (lua_isinteger(L, -1)) 112 | lua_pushinteger(R, lua_tointeger(L, -1)); 113 | else 114 | lua_pushnumber(R, lua_tonumber(L, -1)); 115 | break; 116 | case LUA_TSTRING: 117 | lua_pushstring(R, lua_tostring(L, -1)); 118 | break; 119 | case LUA_TNIL: 120 | lua_pushnil(R); 121 | break; 122 | case LUA_TTABLE: 123 | top = lua_gettop(L); 124 | lua_newtable(R); 125 | lua_pushnil(L); /* first key */ 126 | while (lua_next(L, top) != 0) { 127 | proxy_map(L, R, lua_gettop(R), 0); 128 | lua_pop(L, 1); 129 | } 130 | break; 131 | default: 132 | printf("unknown type %s\n", nam); 133 | } 134 | if (global) { 135 | lua_setglobal(R, nam); 136 | lua_pop(R, 1); 137 | } else 138 | lua_settable(R, t); 139 | 140 | } 141 | 142 | static void 143 | proxy_unmap(lua_State *L, lua_State *R) 144 | { 145 | proxy_object *o; 146 | 147 | switch (lua_type(R, -1)) { 148 | case LUA_TBOOLEAN: 149 | lua_pushboolean(L, lua_toboolean(R, -1)); 150 | break; 151 | case LUA_TNUMBER: 152 | if (lua_isinteger(R, -1)) 153 | lua_pushinteger(L, lua_tointeger(R, -1)); 154 | else 155 | lua_pushnumber(L, lua_tonumber(R, -1)); 156 | break; 157 | case LUA_TSTRING: 158 | lua_pushstring(L, lua_tostring(R, -1)); 159 | break; 160 | case LUA_TNIL: 161 | lua_pushnil(L); 162 | break; 163 | case LUA_TFUNCTION: 164 | case LUA_TTABLE: 165 | o = lua_newuserdata(L, sizeof(proxy_object)); 166 | luaL_getmetatable(L, OBJECT_METATABLE); 167 | lua_setmetatable(L, -2); 168 | o->L = R; 169 | o->ref = luaL_ref(R, LUA_REGISTRYINDEX); 170 | break; 171 | default: 172 | printf("unsupported type %s\n", luaL_typename(R, -1)); 173 | } 174 | } 175 | 176 | static int 177 | proxy_newindex(lua_State *L) 178 | { 179 | proxy_data *p; 180 | 181 | p = luaL_checkudata(L, 1, PROXY_METATABLE); 182 | proxy_map(L, p->L, 0, 1); 183 | return 0; 184 | } 185 | 186 | static int 187 | object_newindex(lua_State *L) 188 | { 189 | proxy_object *o; 190 | 191 | o = luaL_checkudata(L, -3, OBJECT_METATABLE); 192 | 193 | lua_rawgeti(o->L, LUA_REGISTRYINDEX, o->ref); 194 | proxy_map(L, o->L, lua_gettop(o->L), 0); 195 | lua_pop(o->L, 1); 196 | return 0; 197 | } 198 | 199 | static int 200 | object_index(lua_State *L) 201 | { 202 | proxy_object *o; 203 | 204 | o = luaL_checkudata(L, -2, OBJECT_METATABLE); 205 | lua_rawgeti(o->L, LUA_REGISTRYINDEX, o->ref); 206 | 207 | switch (lua_type(L, -1)) { 208 | case LUA_TNUMBER: 209 | if (lua_isinteger(L, -1)) 210 | lua_pushinteger(o->L, lua_tointeger(L, -1)); 211 | else 212 | lua_pushnumber(o->L, lua_tonumber(L, -1)); 213 | break; 214 | case LUA_TSTRING: 215 | lua_pushstring(o->L, lua_tostring(L, -1)); 216 | break; 217 | default: 218 | return luaL_error(L, "proxy: data type '%s' is not " 219 | "supported as an index value", luaL_typename(L, -1)); 220 | } 221 | lua_gettable(o->L, -2); 222 | proxy_unmap(L, o->L); 223 | lua_pop(o->L, 1); 224 | return 1; 225 | } 226 | 227 | static int 228 | object_len(lua_State *L) 229 | { 230 | proxy_object *o; 231 | 232 | o = luaL_checkudata(L, -1, OBJECT_METATABLE); 233 | 234 | lua_rawgeti(o->L, LUA_REGISTRYINDEX, o->ref); 235 | lua_pushinteger(L, lua_rawlen(o->L, -1)); 236 | lua_pop(o->L, 1); 237 | return 1; 238 | } 239 | 240 | static int 241 | object_call(lua_State *L) 242 | { 243 | proxy_object *o; 244 | 245 | o = luaL_checkudata(L, 1, OBJECT_METATABLE); 246 | lua_rawgeti(o->L, LUA_REGISTRYINDEX, o->ref); 247 | lua_pcall(o->L, 0, 0, 0); 248 | lua_pop(o->L, 1); 249 | return 0; 250 | } 251 | 252 | static int 253 | proxy_dostring(lua_State *L) 254 | { 255 | proxy_data *p; 256 | const char *chunk; 257 | 258 | p = luaL_checkudata(L, -2, PROXY_METATABLE); 259 | chunk = luaL_checkstring(L, -1); 260 | (void)luaL_dostring(p->L, chunk); 261 | /* XXX collect return values */ 262 | return 0; 263 | } 264 | 265 | static void 266 | lua_openlib(lua_State *L, const char *name, lua_CFunction fn) 267 | { 268 | lua_pushcfunction(L, fn); 269 | lua_pushstring(L, name); 270 | lua_call(L, 1, 0); 271 | } 272 | 273 | static int 274 | proxy_new(lua_State *L) 275 | { 276 | proxy_data *p; 277 | 278 | p = lua_newuserdata(L, sizeof(proxy_data)); 279 | p->L = luaL_newstate(); 280 | p->close_on_gc = 1; 281 | if (p->L == NULL) { 282 | fprintf(stderr, "can't initialize proxy state"); 283 | return 0; 284 | } 285 | lua_openlib(p->L, "", luaopen_base); 286 | lua_openlib(p->L, LUA_LOADLIBNAME, luaopen_package); 287 | lua_openlib(p->L, LUA_TABLIBNAME, luaopen_table); 288 | lua_openlib(p->L, LUA_STRLIBNAME, luaopen_string); 289 | lua_openlib(p->L, LUA_MATHLIBNAME, luaopen_math); 290 | lua_openlib(p->L, LUA_OSLIBNAME, luaopen_os); 291 | 292 | luaL_getmetatable(L, PROXY_METATABLE); 293 | lua_setmetatable(L, -2); 294 | 295 | return 1; 296 | } 297 | 298 | int 299 | luaopen_proxy(lua_State *L) 300 | { 301 | struct luaL_Reg luaproxy[] = { 302 | { "dostring", proxy_dostring }, 303 | { "new", proxy_new }, 304 | { NULL, NULL } 305 | }; 306 | struct luaL_Reg proxy_methods[] = { 307 | { "__index", proxy_index }, 308 | { "__newindex", proxy_newindex }, 309 | { "__gc", proxy_clear }, 310 | { NULL, NULL } 311 | }; 312 | struct luaL_Reg object_methods[] = { 313 | { "__index", object_index }, 314 | { "__newindex", object_newindex }, 315 | { "__len", object_len }, 316 | { "__call", object_call }, 317 | { "__gc", object_clear }, 318 | { NULL, NULL } 319 | }; 320 | /* The PROXY metatable */ 321 | if (luaL_newmetatable(L, PROXY_METATABLE)) { 322 | luaL_setfuncs(L, proxy_methods, 0); 323 | lua_pushliteral(L, "__metatable"); 324 | lua_pushliteral(L, "must not access this metatable"); 325 | lua_settable(L, -3); 326 | } 327 | lua_pop(L, 1); 328 | if (luaL_newmetatable(L, OBJECT_METATABLE)) { 329 | luaL_setfuncs(L, object_methods, 0); 330 | lua_pushliteral(L, "__metatable"); 331 | lua_pushliteral(L, "must not access this metatable"); 332 | lua_settable(L, -3); 333 | } 334 | lua_pop(L, 1); 335 | luaL_newlib(L, luaproxy); 336 | lua_pushliteral(L, "_COPYRIGHT"); 337 | lua_pushliteral(L, "Copyright (C) 2011 - 2018 by " 338 | "micro systems marc balmer"); 339 | lua_settable(L, -3); 340 | lua_pushliteral(L, "_DESCRIPTION"); 341 | lua_pushliteral(L, "State proxy for Lua"); 342 | lua_settable(L, -3); 343 | lua_pushliteral(L, "_VERSION"); 344 | lua_pushliteral(L, "proxy 1.1.6"); 345 | lua_settable(L, -3); 346 | return 1; 347 | } 348 | -------------------------------------------------------------------------------- /luaproxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 - 2017, Micro Systems Marc Balmer, CH-5073 Gipf-Oberfrick 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of Micro Systems Marc Balmer nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* State proxy Lua */ 29 | 30 | #ifndef __LUA_PROXY__ 31 | #define __LUA_PROXY__ 32 | 33 | #define PROXY_METATABLE "Lua state proxy" 34 | #define OBJECT_METATABLE "Lua state proxy object" 35 | 36 | #define LUA_PROXYLIBNAME "proxy" 37 | 38 | typedef struct { 39 | lua_State *L; /* the proxy state */ 40 | int close_on_gc; 41 | } proxy_data; 42 | 43 | typedef struct { 44 | lua_State *L; /* the proxy state */ 45 | int ref; /* object reference in the proxy state */ 46 | } proxy_object; 47 | 48 | extern int luaopen_proxy(lua_State *L); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /shlib_version: -------------------------------------------------------------------------------- 1 | major=1 2 | minor=0 3 | -------------------------------------------------------------------------------- /test-proxy.lua: -------------------------------------------------------------------------------- 1 | local proxy = require 'proxy' 2 | 3 | 4 | p = proxy.new() 5 | p:dostring([[ 6 | print('This is the proxy state') 7 | 8 | print('n is:') 9 | print(n) 10 | ]]) 11 | 12 | local t2 = {{id = 42, text = ' foo'}, {id = 10, text = 'bar'}} 13 | 14 | p.t2 = t2 15 | 16 | print(p.t2[2].text) 17 | 18 | p.n = 42 -- creates n in the proxy state 19 | p:dostring([[print('n is ' .. n) n = n + 1]]) 20 | print(p.n) 21 | 22 | p.Query = { 23 | op = 'test', 24 | num = 73 25 | } 26 | 27 | print('print in the proxy') 28 | p:dostring([[print(Query.op) print(Query.num)]]) 29 | 30 | print('print locally') 31 | print(p.Query.op) 32 | print(p.Query.num) 33 | 34 | p.Query.num = 15 35 | 36 | p:dostring('print(Query.num)') 37 | 38 | t = { 39 | a = 1, 40 | b = true, 41 | c = 3 42 | } 43 | 44 | p.t = t 45 | 46 | p:dostring('print(t.a) print(t.b) print(t.c)') 47 | 48 | p:dostring([[print('n is now ' .. n)]]) 49 | 50 | 51 | print("abc " .. p.Query.op) 52 | 53 | p:dostring([[function test () 54 | print('this is the test function in the proxy') 55 | end 56 | print('function test created')]]) 57 | 58 | p.test() 59 | 60 | print('index tests') 61 | 62 | p.posgroup = {} 63 | p.posgroup[1] = { 64 | name = 'abc' 65 | } 66 | 67 | print('--- create table at index 2') 68 | 69 | p.posgroup[2] = {} 70 | 71 | print('--- set def ') 72 | 73 | p.posgroup[2].name = 'def' 74 | 75 | print('--- set sale as table') 76 | 77 | p.posgroup[2].sale = {} 78 | 79 | 80 | print('finally') 81 | 82 | p:dostring([[ 83 | print(posgroup.name) 84 | 85 | for k, item in pairs(posgroup) do 86 | print(item.name) 87 | end 88 | ]]) 89 | 90 | print('---') 91 | 92 | images = {} 93 | for n = 1, 110 do 94 | images[n] = { 95 | id = 10, 96 | name = 'test', 97 | descr = 'descr', 98 | threshold = 100 99 | } 100 | end 101 | 102 | p.images = {} 103 | for n = 1, 110 do 104 | p.images[n] = { 105 | id = 10, 106 | name = 'test', 107 | descr = 'descr', 108 | threshold = 100 109 | } 110 | end 111 | print('length of p.images', #p.images) 112 | print('end') 113 | -------------------------------------------------------------------------------- /vars.lua: -------------------------------------------------------------------------------- 1 | require "proxy" 2 | 3 | p = proxy.new() 4 | 5 | p.asset = {} 6 | for n = 1, 5 do 7 | p.asset[n] = { 8 | name = 'asset ' .. n 9 | } 10 | end 11 | 12 | p:dostring([[ 13 | for n = 1, 5 do 14 | print(asset[n].name) 15 | end 16 | 17 | for i, v in pairs(asset) do 18 | print(i) 19 | print(v.name) 20 | for j, k in pairs(v) do 21 | print(j) 22 | print(k) 23 | end 24 | end 25 | 26 | ]]) 27 | 28 | --------------------------------------------------------------------------------