Skip to content

Commit b5d7360

Browse files
committed
Patch package.searchers with functions using the patched searchpath
1 parent 51f75f4 commit b5d7360

File tree

4 files changed

+79
-9
lines changed

4 files changed

+79
-9
lines changed

SConstruct

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ env.Command(
1313
[
1414
"src/generated/global_enums.hpp",
1515
"src/generated/utility_functions.hpp",
16+
"src/generated/package_searcher.h",
1617
],
1718
[
1819
"src/generate_code.py",
20+
"src/luaopen/package_searcher.lua",
1921
"lib/godot-cpp/gdextension/extension_api.json",
2022
"lib/godot-cpp/gen/include/godot_cpp/variant/utility_functions.hpp",
2123
],

src/generate_code.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
SRC_DIR = os.path.dirname(__file__)
55
DEST_DIR = os.path.join(SRC_DIR, "generated")
66
API_JSON_PATH = os.path.join(SRC_DIR, "..", "lib", "godot-cpp", "gdextension", "extension_api.json")
7+
PACKAGE_SEARCHER_SRC = os.path.join(SRC_DIR, "luaopen", "package_searcher.lua")
78
PRIMITIVE_VARIANTS = [
89
"bool",
910
"int",
@@ -18,7 +19,8 @@
1819

1920
def generate_utility_functions(utility_functions):
2021
lines = [
21-
"#undef register_utility_functions\n#define register_utility_functions(state)"
22+
"// This file was automatically generated by generate_code.py",
23+
"#undef register_utility_functions\n#define register_utility_functions(state)",
2224
]
2325
for f in utility_functions:
2426
name = f["name"]
@@ -39,7 +41,8 @@ def generate_utility_functions(utility_functions):
3941

4042
def generate_enums(global_enums):
4143
lines = [
42-
"#undef register_global_enums\n#define register_global_enums(state)"
44+
"// This file was automatically generated by generate_code.py",
45+
"#undef register_global_enums\n#define register_global_enums(state)",
4346
]
4447
for enum in global_enums:
4548
lines.append(f"\t/* {enum['name']} */")
@@ -48,6 +51,19 @@ def generate_enums(global_enums):
4851
return " \\\n".join(lines) + "\n"
4952

5053

54+
def generate_package_searcher():
55+
lines = [
56+
"// This file was automatically generated by generate_code.py",
57+
"const char package_searcher_lua[] = ",
58+
]
59+
with open(PACKAGE_SEARCHER_SRC, "r") as f:
60+
for line in f:
61+
line = line.replace("\\", "\\\\").replace('"', '\\"').rstrip("\r\n")
62+
lines.append('"' + line + '\\n"')
63+
lines.append(";")
64+
return "\n".join(lines)
65+
66+
5167
def main():
5268
with open(API_JSON_PATH) as f:
5369
api = json.load(f)
@@ -60,6 +76,10 @@ def main():
6076
with open(os.path.join(DEST_DIR, "global_enums.hpp"), "w") as f:
6177
code = generate_enums(api["global_enums"])
6278
f.write(code)
79+
80+
with open(os.path.join(DEST_DIR, "package_searcher.h"), "w") as f:
81+
code = generate_package_searcher()
82+
f.write(code)
6383

6484

6585
if __name__ == "__main__":

src/luaopen/local_paths.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,27 @@
3131
#include <godot_cpp/classes/os.hpp>
3232
#include <godot_cpp/classes/project_settings.hpp>
3333

34+
#include "../generated/package_searcher.h"
35+
3436
using namespace luagdextension;
3537

36-
static int searchpath(lua_State *L, const String& name, const String& path, const String& sep, const String& rep) {
37-
String template_name = sep.is_empty() ? name : name.replace(sep, rep);
38+
static int l_searchpath(lua_State *L) {
39+
String name = luaL_checkstring(L, 1);
40+
String path = luaL_checkstring(L, 2);
41+
String sep = luaL_optstring(L, 3, ".");
42+
String rep = luaL_optstring(L, 4, "/");
43+
if (!sep.is_empty()) {
44+
name = name.replace(sep, rep);
45+
}
46+
3847
String execdir_repl = Engine::get_singleton()->is_editor_hint()
3948
? ProjectSettings::get_singleton()->globalize_path("res://")
4049
: OS::get_singleton()->get_executable_path().get_base_dir();
4150

4251
PackedStringArray path_list = path.split(";", false);
4352
PackedStringArray not_found_list;
4453
for (const String& path_template : path_list) {
45-
String filename = path_template.replace("?", template_name).replace("!", execdir_repl);
54+
String filename = path_template.replace("?", name).replace("!", execdir_repl);
4655
if (FileAccess::file_exists(filename)) {
4756
sol::stack::push(L, filename);
4857
return 1;
@@ -62,10 +71,6 @@ static int searchpath(lua_State *L, const String& name, const String& path, cons
6271
return 2;
6372
}
6473

65-
static int l_searchpath(lua_State *L) {
66-
return searchpath(L, luaL_checkstring(L, 1), luaL_checkstring(L, 2), luaL_optstring(L, 3, "."), luaL_optstring(L, 4, "/"));
67-
}
68-
6974
static int l_loadfile(lua_State *L) {
7075
sol::state_view state(L);
7176
String filename = luaL_optstring(L, 1, "");
@@ -107,6 +112,7 @@ extern "C" int luaopen_godot_local_paths(lua_State *L) {
107112

108113
if (auto package = state.get<sol::optional<sol::table>>("package")) {
109114
(*package)["searchpath"] = l_searchpath;
115+
state.do_string(package_searcher_lua);
110116
}
111117

112118
state["loadfile"] = l_loadfile;

src/luaopen/package_searcher.lua

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
local loadlib, searchpath = package.loadlib, package.searchpath
2+
3+
local function lua_searcher(name)
4+
local filename, err = searchpath(name, package.path)
5+
if filename then
6+
return assert(loadfile(filename))
7+
else
8+
return err
9+
end
10+
end
11+
12+
local function c_searcher(name, name_override)
13+
local filename, err = searchpath(name, package.cpath)
14+
if not filename then
15+
return err
16+
end
17+
18+
local func_suffix = (name_override or name):replace(".", "_")
19+
-- Split module name if a "-" is found
20+
local igmark = func_suffix:find("-", 1, false)
21+
if igmark then
22+
local funcname = "luaopen_" .. func_suffix:sub(1, igmark - 1)
23+
local f = loadlib(filename, funcname)
24+
if f then return f end
25+
func_suffix = func_suffix:sub(igmark + 1)
26+
end
27+
local f, err = loadlib(filename, "luaopen_" .. func_suffix)
28+
return assert(f, ("error loading module %q from file %q:\n\t%s"):format(name_override or name, filename, err))
29+
end
30+
31+
local function c_root_searcher(name)
32+
local root_name = name:match("^([^.]+)%.")
33+
if not root_name then
34+
return nil
35+
end
36+
return c_searcher(root_name, name)
37+
end
38+
39+
local searchers = package.searchers or package.loaders
40+
searchers[2] = lua_searcher
41+
searchers[3] = c_searcher
42+
searchers[4] = c_root_searcher

0 commit comments

Comments
 (0)