Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # for mingw | ||
|
|
||
| LUAINC = -I../src | ||
| LUALIB = -L../src/ -llua54 | ||
| CFLAGS = -Wall -g | ||
| SHARED = --shared | ||
|
|
||
| all : sharetable.dll multivm.dll | ||
|
|
||
| sharetable.dll : sharetable.c | ||
| gcc $(CFLAGS) $(SHARED) -o $@ $^ $(LUAINC) $(LUALIB) | ||
|
|
||
| multivm.dll : multivm.c | ||
| gcc $(CFLAGS) $(SHARED) -o $@ $^ $(LUAINC) $(LUALIB) | ||
|
|
||
| clean : | ||
| rm sharetable.dll multivm.dll | ||
|
|
||
| test : | ||
| ../src/lua.exe test.lua | ||
|
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| #define LUA_LIB | ||
|
|
||
| #include <lua.h> | ||
| #include <lauxlib.h> | ||
| #include <lualib.h> | ||
|
|
||
| struct boxvm { | ||
| lua_State *L; | ||
| }; | ||
|
|
||
| static int | ||
| lvm_delete(lua_State *L) { | ||
| struct boxvm *vm = lua_touserdata(L, 1); | ||
| if (vm->L) { | ||
| lua_close(vm->L); | ||
| vm->L = NULL; | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| static int | ||
| vm_init(lua_State *L) { | ||
| luaL_openlibs(L); | ||
| return 0; | ||
| } | ||
|
|
||
| static int | ||
| vm_dostring(lua_State *L) { | ||
| const char *code = (const char *)lua_touserdata(L, 1); | ||
| lua_pop(L, 1); | ||
| luaL_loadstring(L, code); | ||
| lua_call(L, 0, LUA_MULTRET); | ||
| return lua_gettop(L); | ||
| } | ||
|
|
||
| static int | ||
| lvm_dostring(lua_State *L) { | ||
| luaL_checktype(L, 1, LUA_TUSERDATA); | ||
| struct boxvm *vm = lua_touserdata(L, 1); | ||
| lua_State *cL = vm->L; | ||
| const char * code = luaL_checkstring(L, 2); | ||
| lua_settop(cL, 0); | ||
| lua_pushcfunction(cL, vm_dostring); | ||
| lua_pushlightuserdata(cL, (void *)code); | ||
| if (lua_pcall(cL, 1, LUA_MULTRET, 0) != LUA_OK) { | ||
| const char * err = lua_tostring(cL, -1); | ||
| lua_pushstring(L, err); | ||
| lua_pop(cL, 1); | ||
| return lua_error(L); | ||
| } | ||
| int retn = lua_gettop(cL); | ||
| int i; | ||
| for (i=1;i<=retn;i++) { | ||
| switch(lua_type(cL, i)) { | ||
| case LUA_TBOOLEAN: | ||
| lua_pushboolean(L, lua_toboolean(cL, i)); | ||
| break; | ||
| case LUA_TNUMBER: | ||
| if (lua_isinteger(cL, i)) { | ||
| lua_pushinteger(L, lua_tointeger(cL, i)); | ||
| } else { | ||
| lua_pushnumber(L, lua_tonumber(cL, i)); | ||
| } | ||
| break; | ||
| case LUA_TLIGHTUSERDATA: | ||
| lua_pushlightuserdata(L, lua_touserdata(cL, i)); | ||
| break; | ||
| default: | ||
| return luaL_error(L, "Unsupported return type %s", lua_typename(L, lua_type(cL, i))); | ||
| } | ||
| } | ||
| return retn; | ||
| } | ||
|
|
||
| static int | ||
| lnew_vm(lua_State *L) { | ||
| struct boxvm *vm = lua_newuserdata(L, sizeof(struct boxvm)); | ||
| vm->L = NULL; | ||
| if (luaL_newmetatable(L, "MULTIVM")) { | ||
| luaL_Reg meta[] = { | ||
| { "__gc", lvm_delete }, | ||
| { "__index", NULL }, | ||
| { "dostring", lvm_dostring }, | ||
| { NULL, NULL }, | ||
| }; | ||
| luaL_setfuncs(L, meta, 0); | ||
| lua_pushvalue(L, -1); | ||
| lua_setfield(L, -2, "__index"); | ||
| } | ||
| lua_setmetatable(L, -2); | ||
| vm->L = luaL_newstate(); | ||
| lua_pushcfunction(vm->L, vm_init); | ||
| if (lua_pcall(vm->L, 0, 0, 0) != LUA_OK) { | ||
| lua_close(vm->L); | ||
| vm->L = NULL; | ||
| return luaL_error(L, "new vm failed"); | ||
| } | ||
| return 1; | ||
| } | ||
|
|
||
| LUAMOD_API int | ||
| luaopen_multivm(lua_State *L) { | ||
| luaL_checkversion(L); | ||
| luaL_Reg l[] = { | ||
| { "new", lnew_vm }, | ||
| { NULL, NULL }, | ||
| }; | ||
| luaL_newlib(L, l); | ||
| return 1; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| #define LUA_LIB | ||
|
|
||
| #include <lua.h> | ||
| #include <lauxlib.h> | ||
| #include <lualib.h> | ||
|
|
||
| #include "lgc.h" | ||
|
|
||
| #ifdef makeshared | ||
|
|
||
| static void | ||
| mark_shared(lua_State *L) { | ||
| if (lua_type(L, -1) != LUA_TTABLE) { | ||
| luaL_error(L, "Not a table, it's a %s.", lua_typename(L, lua_type(L, -1))); | ||
| } | ||
| Table * t = (Table *)lua_topointer(L, -1); | ||
| if (isshared(t)) | ||
| return; | ||
| makeshared(t); | ||
| luaL_checkstack(L, 4, NULL); | ||
| if (lua_getmetatable(L, -1)) { | ||
| luaL_error(L, "Can't share metatable"); | ||
| } | ||
| lua_pushnil(L); | ||
| while (lua_next(L, -2) != 0) { | ||
| int i; | ||
| for (i=0;i<2;i++) { | ||
| int idx = -i-1; | ||
| int t = lua_type(L, idx); | ||
| switch (t) { | ||
| case LUA_TTABLE: | ||
| mark_shared(L); | ||
| break; | ||
| case LUA_TNUMBER: | ||
| case LUA_TBOOLEAN: | ||
| case LUA_TLIGHTUSERDATA: | ||
| break; | ||
| case LUA_TFUNCTION: | ||
| if (lua_getupvalue(L, idx, 1) != NULL) { | ||
| luaL_error(L, "Invalid function with upvalue"); | ||
| } else if (!lua_iscfunction(L, idx)) { | ||
| LClosure *f = (LClosure *)lua_topointer(L, idx); | ||
| makeshared(f); | ||
| } | ||
| break; | ||
| case LUA_TSTRING: | ||
| lua_sharestring(L, idx); | ||
| break; | ||
| default: | ||
| luaL_error(L, "Invalid type [%s]", lua_typename(L, t)); | ||
| break; | ||
| } | ||
| } | ||
| lua_pop(L, 1); | ||
| } | ||
| } | ||
|
|
||
| static int | ||
| lis_sharedtable(lua_State* L) { | ||
| int b = 0; | ||
| if(lua_type(L, 1) == LUA_TTABLE) { | ||
| Table * t = (Table *)lua_topointer(L, 1); | ||
| b = isshared(t); | ||
| } | ||
| lua_pushboolean(L, b); | ||
| return 1; | ||
| } | ||
|
|
||
| static int | ||
| lmark_shared(lua_State *L) { | ||
| // turn off gc , because marking shared will prevent gc mark. | ||
| lua_gc(L, LUA_GCSTOP, 0); | ||
| mark_shared(L); | ||
| Table * t = (Table *)lua_topointer(L, -1); | ||
| lua_pushlightuserdata(L, t); | ||
| return 1; | ||
| } | ||
|
|
||
| static int | ||
| lclone_table(lua_State *L) { | ||
| lua_clonetable(L, lua_touserdata(L, 1)); | ||
|
|
||
| return 1; | ||
| } | ||
|
|
||
| LUAMOD_API int | ||
| luaopen_sharetable(lua_State *L) { | ||
| luaL_checkversion(L); | ||
| luaL_Reg l[] = { | ||
| { "clone", lclone_table }, | ||
| { "mark_shared", lmark_shared }, | ||
| { "is_sharedtable", lis_sharedtable }, | ||
| { NULL, NULL }, | ||
| }; | ||
| luaL_newlib(L, l); | ||
| return 1; | ||
| } | ||
|
|
||
| #else | ||
|
|
||
| LUAMOD_API int | ||
| luaopen_sharetable(lua_State *L) { | ||
| return luaL_error(L, "Not supported"); | ||
| } | ||
|
|
||
| #endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| local sharetable = require "sharetable" | ||
| local multivm = require "multivm" | ||
|
|
||
| local vm = multivm.new() | ||
|
|
||
| local testp, tablep = vm:dostring [[ | ||
| local sharetable = require "sharetable" | ||
| _G.test = { "Hello", "World" } | ||
| local testp = sharetable.mark_shared(_G.test) | ||
| local tablep = sharetable.mark_shared(_G.table) | ||
| return testp, tablep | ||
| ]] | ||
|
|
||
| local shared_test = sharetable.clone(testp) | ||
| local shared_table = sharetable.clone(tablep) | ||
|
|
||
| -- Use table.unpack in vm to unpack _G.test in vm. | ||
| print(shared_table.unpack(shared_test)) |