X-Git-Url: http://git.squeep.com/?p=lemu;a=blobdiff_plain;f=lua_interface.c;fp=lua_interface.c;h=03496e85ddd7f3c8adbb4e6003266636ad87277b;hp=0000000000000000000000000000000000000000;hb=3c54afe11e890fc476cc4730226be1c45f8a04cb;hpb=29235d4c1f0b11bd2efcad262eaae70383228293 diff --git a/lua_interface.c b/lua_interface.c new file mode 100644 index 0000000..03496e8 --- /dev/null +++ b/lua_interface.c @@ -0,0 +1,168 @@ +#include + +#include +#include +#include + +#include "connections.h" +#include "lua_interface.h" +#include "notify.h" + +#define CONNECTION_META_TABLE "MetaConnection" +#define CONNECTION_TABLE "Connection" +#define CONNECTION_TABLE_UD_FIELD "core_" + +/** + * HARD: shared common server state, updatable commands table + * Interim: independent states, any global changes queued to all workers + * Idea: can a proxy table be crafted to access a shared table-like c entity + * Idea: eventual-consistency between lua states (somehow) + * + */ + + +/** + * Create a new referenced coroutine on lua state. + * release with: + * luaL_unref(L, LUA_REGISTRYINDEX, refkey); + */ +int +lua_new_coroutine_ref(lua_State *L, lua_State **coL, int *refkey) +{ + *refkey = LUA_NOREF; + + /* Create new coroutine on top of stack. */ + *coL = lua_newthread(L); + if (!*coL) { + NOTIFY_ERROR("%s:%s", "lua_newthread", "failed"); + return -1; + } + + /* Store coroutine reference in state registry. */ + *refkey = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; +} + + +/** + * Connection Object + * is a table with metatable for methods and userdata field + * + */ + + +/** + * Add a connection reference to lua stack + * + */ +int +lemu_connection_push(lua_State *L, struct connection *c) +{ + connection_inc_ref(c); + + lua_newtable(L); // new connection table + luaL_getmetatable(L, CONNECTION_META_TABLE); // locate meta + lua_setmetatable(L, -2); // assign meta to connection table + + /* keeping a pointer in userdata, rather than light userdata, to get metatable support */ + struct connection **cud = lua_newuserdatauv(L, sizeof c, 0); + *cud = c; + luaL_getmetatable(L, CONNECTION_META_TABLE); + lua_setmetatable(L, -2); + + lua_setfield(L, -2, CONNECTION_TABLE_UD_FIELD); + return 1; +} + + +/** + * I guess this one would take a stack value to find a connection + */ +static int +lemu_connection_create_(lua_State *L) +{ + struct connection *c; + + luaL_checktype(L, 1, LUA_TSTRING); + // c = connection_lookup(lua_tostring(L, 1)); + c = NULL; + + return lemu_connection_push(L, c); +} + + +/** + * this will only get called on userdata (how does that happen??) + */ +static int +lemu_connection_destroy_(lua_State *L) +{ + struct connection **cud = luaL_checkudata(L, 1, CONNECTION_META_TABLE); + struct connection *c = *cud; + + connection_free(c); + + return 0; +} + + +/** + * Send a fixed string to a connection. + */ +static int +lemu_connection_send_(lua_State *L) +{ + if (lua_gettop(L) < 2) { + lua_pushliteral(L, "too few arguments"); + lua_error(L); + } + luaL_checktype(L, 1, LUA_TTABLE); + lua_getfield(L, 1, CONNECTION_TABLE_UD_FIELD); + luaL_checktype(L, -1, LUA_TUSERDATA); + struct connection **cud = lua_touserdata(L, -1); + struct connection *c = *cud; + + luaL_checktype(L, 2, LUA_TSTRING); + const char *message = lua_tostring(L, 2); + + connection_printf(c, "%s\n", message); + + return 0; +} + + +static const luaL_Reg Connection_funcs[] = { + { "create", lemu_connection_create_ }, + { NULL, NULL } +}; + + +static const luaL_Reg Connection_methods[] = { + { "__gc", lemu_connection_destroy_ }, + { "send", lemu_connection_send_ }, + { NULL, NULL } +}; + + +/** + * Initialize the Connection object prototypes + */ +int +lemu_connection_luainit(lua_State *L) +{ + luaL_newmetatable(L, CONNECTION_META_TABLE); // new userdata metatable, __name = CONNECTION_META_TABLE + lua_pushstring(L, "__index"); + lua_pushvalue(L, -2); // meta table + lua_settable(L, -3); // becomes its own index table + luaL_setfuncs(L, Connection_methods, 0); // add methods to metatable + lua_pop(L, 1); + + luaL_newlibtable(L, Connection_funcs); // new table with functions + luaL_setfuncs(L, Connection_funcs, 0); + lua_setglobal(L, CONNECTION_TABLE); // make it available + + return 0; +} + +// int luaopen_lemu(lua_State *L);