Skip to content

Instantly share code, notes, and snippets.

@actboy168
Created February 20, 2025 16:57
Show Gist options
  • Save actboy168/28df99cdea6ff015f8c51737214f9e03 to your computer and use it in GitHub Desktop.
Save actboy168/28df99cdea6ff015f8c51737214f9e03 to your computer and use it in GitHub Desktop.
local fs = require "bee.filesystem"
local code_main <const> = [[
#include <lua.hpp>
static int push_preload_table(lua_State *L);
static int searcher(lua_State *L) {
const char *name = luaL_checkstring(L, 1);
lua_pushvalue(L, 1);
if (LUA_TNIL == lua_rawget(L, lua_upvalueindex(1))) {
lua_pushfstring(L, "no module '%s'", name);
return 1;
}
lua_call(L, 0, 1);
const char* str = lua_tostring(L, -1);
lua_Unsigned len = lua_rawlen(L, -1);
if (luaL_loadbuffer(L, str, (size_t)len, str) == LUA_OK) {
lua_pushstring(L, name);
return 2;
}
else {
return luaL_error(L, "error loading module '%s':\n\t%s", name, lua_tostring(L, -1));
}
}
static int push_searcher(lua_State *L) {
push_preload_table(L);
lua_pushcclosure(L, searcher, 1);
return 1;
}
#define REG_SOURCE(module, name) \
lua_pushlightuserdata(L, (void *)name); \
lua_pushinteger(L, sizeof(name)); \
lua_pushcclosure(L, get_string, 2); \
lua_setfield(L, -2, module);
static int get_string(lua_State *L) {
const char* str = (const char *)lua_touserdata(L, lua_upvalueindex(1));
size_t len = (size_t)lua_tointeger(L, lua_upvalueindex(2));
lua_pushlstring(L, str, len);
return 1;
}
]]
local code_reg <const> = [[REG_SOURCE($module, $name)]]
local code_bin <const> = [[
static const unsigned char $name[] = {
$bytes
};
]]
local code_push <const> = [[
static int push_preload_table(lua_State *L) {
lua_createtable(L, 0, $num);
$reg
return 1;
}
]]
local function readall(path)
local file <close> = assert(io.open(path, "rb"))
return file:read "a"
end
local function compile(content, symbol)
local count = 0
local function tohex(c)
local b = string.format("0x%02x,", c:byte())
count = count + 1
if count == 16 then
b = b.."\n "
count = 0
end
return b
end
local func = assert(load(content, "@"..symbol))
local bin = string.dump(func)
return bin:gsub(".", tohex)
end
local function embed(file, list, content, symbol)
local cpp_symbol = "luasrc_"..symbol:match("^(.+)%.lua$"):gsub("/", "_")
list[#list+1] = code_reg:gsub("$(%w+)", {
name = cpp_symbol,
module = symbol:match("^(.+)%.lua$"):gsub("/", "."),
})
local output = code_bin:gsub("$(%w+)", {
name = cpp_symbol,
bytes = compile(content, symbol),
})
file:write(output)
file:write "\n"
end
local file <close> = assert(io.open("test.cpp", "wb"))
do
file:write(code_main)
file:write "\n"
end
local list = {}
for path, status in fs.pairs_r "scripts" do
if not status:is_directory() and path:extension() == ".lua" then
local filename = path:string()
local symbol = filename:sub(9)
embed(file, list, readall(filename), symbol)
end
end
embed(file, list, readall "main.lua", "main.lua")
do
local output = code_push:gsub("$(%w+)", {
num = #list,
reg = table.concat(list, "\n "),
})
file:write(output)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment