Skip to content

Commit 8e4c348

Browse files
committed
Add libgodot skeleton project
1 parent f748e85 commit 8e4c348

File tree

8 files changed

+189
-15
lines changed

8 files changed

+189
-15
lines changed

libgodot/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/src

libgodot/README.md

Whitespace-only changes.

libgodot/copy_data.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#! /usr/bin/env python3
2+
3+
from __future__ import annotations
4+
import argparse
5+
from pathlib import Path
6+
import shutil
7+
8+
9+
BASE_DIR = Path(__file__).parent
10+
ROOT_DIR = BASE_DIR / ".."
11+
TARGET_DIR = BASE_DIR / "src"
12+
13+
14+
def copy_data(build_dir: Path) -> None:
15+
output_godot_dir = TARGET_DIR / "godot"
16+
output_godot_hazmat_dir = output_godot_dir / "hazmat"
17+
output_godot_hazmat_dir.mkdir(parents=True, exist_ok=True)
18+
19+
shutil.copy(ROOT_DIR / "src/_gdpy_libgodot.pyx", TARGET_DIR)
20+
shutil.copy(build_dir / "src/pythonscript_gdextension_ptrs.c", TARGET_DIR)
21+
22+
shutil.copytree(build_dir / "gdextension_api", TARGET_DIR / "gdextension_api")
23+
24+
src_godot_dir = ROOT_DIR / "src/godot"
25+
shutil.copy(src_godot_dir / "__init__.py", output_godot_dir)
26+
shutil.copy(src_godot_dir / "__init__.pyi", output_godot_dir)
27+
shutil.copy(src_godot_dir / "_lang.pyx", output_godot_dir)
28+
shutil.copy(src_godot_dir / "_lang_resource_format_loader.pxi", output_godot_dir)
29+
shutil.copy(src_godot_dir / "_lang_resource_format_saver.pxi", output_godot_dir)
30+
shutil.copy(src_godot_dir / "_lang_script_language.pxi", output_godot_dir)
31+
shutil.copy(src_godot_dir / "_lang_script.pxi", output_godot_dir)
32+
shutil.copy(src_godot_dir / "py.typed", output_godot_dir)
33+
shutil.copy(src_godot_dir / "singletons.py", output_godot_dir)
34+
35+
build_src_godot_dir = build_dir / "src/godot"
36+
shutil.copy(build_src_godot_dir / "builtins.pyx", output_godot_dir)
37+
shutil.copy(build_src_godot_dir / "builtins.pyi", output_godot_dir)
38+
shutil.copy(build_src_godot_dir / "builtins.pxd", output_godot_dir)
39+
shutil.copy(build_src_godot_dir / "classes.pyx", output_godot_dir)
40+
shutil.copy(build_src_godot_dir / "classes.pyi", output_godot_dir)
41+
shutil.copy(build_src_godot_dir / "classes.pxd", output_godot_dir)
42+
shutil.copy(build_src_godot_dir / "_version.py", output_godot_dir)
43+
44+
src_godot_hazmat_dir = src_godot_dir / "hazmat"
45+
shutil.copy(src_godot_hazmat_dir / "extension_class.pxd", output_godot_hazmat_dir)
46+
shutil.copy(src_godot_hazmat_dir / "extension_class.pyx", output_godot_hazmat_dir)
47+
shutil.copy(src_godot_hazmat_dir / "__init__.py", output_godot_hazmat_dir)
48+
49+
build_src_godot_hazmat_dir = build_src_godot_dir / "hazmat"
50+
shutil.copy(build_src_godot_hazmat_dir / "gdapi.pxd", output_godot_hazmat_dir)
51+
shutil.copy(build_src_godot_hazmat_dir / "gdextension_interface.pxd", output_godot_hazmat_dir)
52+
shutil.copy(build_src_godot_hazmat_dir / "gdptrs.pxd", output_godot_hazmat_dir)
53+
shutil.copy(build_src_godot_hazmat_dir / "gdtypes.pxd", output_godot_hazmat_dir)
54+
55+
56+
if __name__ == "__main__":
57+
parser = argparse.ArgumentParser(
58+
description="Generate a Python project embedding LibGodot & Godot-Python bindings"
59+
)
60+
parser.add_argument(
61+
"--input",
62+
"-i",
63+
required=True,
64+
metavar="BUILD_PATH",
65+
type=Path,
66+
default=BASE_DIR / "../build",
67+
)
68+
parser.add_argument(
69+
"--force",
70+
"-f",
71+
action="store_true",
72+
)
73+
74+
args = parser.parse_args()
75+
76+
if TARGET_DIR.exists():
77+
if args.force:
78+
shutil.rmtree(TARGET_DIR)
79+
else:
80+
raise RuntimeError(f"{TARGET_DIR} already exists, aborting")
81+
82+
copy_data(build_dir=args.input)

libgodot/pyproject.toml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[project]
2+
name = "godot-python"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
readme = "README.md"
6+
requires-python = ">=3.13"
7+
dependencies = []
8+
9+
[build-system]
10+
requires = [
11+
"setuptools>=80.9.0",
12+
"cython~=3.1",
13+
]
14+
build-backend = "setuptools.build_meta"
15+
16+
[tool.setuptools]
17+
18+
# Do not include files listed in MANIFEST.in to wheels.
19+
include-package-data = false
20+
21+
[[tool.setuptools.ext-modules]]
22+
name = "_pythonscript"
23+
sources = [
24+
"src/pythonscript_gdextension_ptrs.c",
25+
"src/_gdpy_libgodot.pyx",
26+
]
27+
include-dirs = ["./src/gdextension_api/"]
28+
extra-compile-args = ["-O0"]
29+
30+
[[tool.setuptools.ext-modules]]
31+
name = "godot.builtins"
32+
sources = ["./src/godot/builtins.pyx"]
33+
include-dirs = ["./src/gdextension_api/"]
34+
extra-compile-args = ["-O0"]
35+
36+
[[tool.setuptools.ext-modules]]
37+
name = "godot.classes"
38+
sources = ["./src/godot/classes.pyx"]
39+
include-dirs = ["./src/gdextension_api/"]
40+
extra-compile-args = ["-O0"]
41+
42+
[[tool.setuptools.ext-modules]]
43+
name = "godot._lang"
44+
sources = ["./src/godot/_lang.pyx"]
45+
include-dirs = ["./src/gdextension_api/"]
46+
extra-compile-args = ["-O0"]
47+
48+
[[tool.setuptools.ext-modules]]
49+
name = "godot.hazmat.extension_class"
50+
sources = ["src/godot/hazmat/extension_class.pyx"]
51+
include-dirs = ["./src/gdextension_api/"]
52+
extra-compile-args = ["-O0"]

libgodot/uv.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ dev = [
2929
[tool.ruff]
3030
line-length = 100
3131
target-version = "py313"
32+
33+
[tool.uv.workspace]
34+
members = [
35+
"libgodot/",
36+
]

src/_gdpy_libgodot.pyx

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,17 @@ from godot.classes cimport BaseGDObject
77

88

99
# LibGodot API
10-
cdef extern from "*":
10+
cdef extern from *:
11+
"""
12+
typedef struct {
13+
const char* key;
14+
void* val;
15+
} LibGodotExtensionParameter;
16+
17+
GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func, LibGodotExtensionParameter *p_params);
18+
void libgodot_destroy_godot_instance(GDExtensionObjectPtr p_godot_instance);
19+
"""
20+
1121
ctypedef struct LibGodotExtensionParameter:
1222
const char* key
1323
void* val
@@ -34,9 +44,10 @@ def create_godot_instance(argv: list[str]):
3444
if gd_instance == NULL:
3545
raise RuntimeError("Failed to create Godot instance")
3646

47+
cdef BaseGDObject instance
3748
try:
3849
from godot.classes import GodotInstance
39-
cdef BaseGDObject instance = GodotInstance.__new__(GodotInstance)
50+
instance = GodotInstance.__new__(GodotInstance)
4051
_libgodot_instance = instance
4152

4253
_libgodot_init_lock.release()
@@ -45,7 +56,7 @@ def create_godot_instance(argv: list[str]):
4556

4657
finally:
4758
with _libgodot_init_lock:
48-
libgodot_destroy_godot_instance(instance._gd_instance)
59+
libgodot_destroy_godot_instance(instance._gd_ptr)
4960
_libgodot_instance = None
5061

5162

@@ -59,13 +70,13 @@ cdef GDExtensionObjectPtr _create_godot_instance(argv: list[str]):
5970
assert c_argv != NULL
6071
try:
6172
for i in range(length):
62-
c_argv[i] = <const char*>pybytes_argv
73+
c_argv[i] = <char*>pybytes_argv
6374

6475
# `c_argv` is ready, now we can initialize Godot instance !
6576
return libgodot_create_godot_instance(
6677
len(argv),
6778
c_argv,
68-
pythonscript_init,
79+
_pythonscript_init,
6980
NULL
7081
)
7182

@@ -80,17 +91,21 @@ cdef GDExtensionObjectPtr _create_godot_instance(argv: list[str]):
8091

8192
# Those symbols are defined in `pythonscript_gdextension_ptrs.c` which is
8293
# going to be compiled together with this file into a single shared library.
83-
cdef extern from "*":
94+
cdef extern from *:
95+
"""
96+
void init_pythonscript_gdextension();
97+
"""
98+
8499
const GDExtensionInterfaceGetProcAddress pythonscript_gdptr_get_proc_address
85100
const GDExtensionClassLibraryPtr pythonscript_gdptr_library
86101
void init_pythonscript_gdextension()
87102

88103

89-
cdef public GDExtensionBool pythonscript_init(
90-
const GDExtensionInterfaceGetProcAddress p_get_proc_address,
91-
const GDExtensionClassLibraryPtr p_library,
104+
cdef GDExtensionBool _pythonscript_init(
105+
GDExtensionInterfaceGetProcAddress p_get_proc_address,
106+
GDExtensionClassLibraryPtr p_library,
92107
GDExtensionInitialization *r_initialization
93-
):
108+
) noexcept with gil:
94109
print('[libgodot] pythonscript_init()', flush=True)
95110

96111
# `pythonscript_gdptr_*` must be set as early as possible given it is never
@@ -107,22 +122,22 @@ cdef public GDExtensionBool pythonscript_init(
107122
# Initialize as early as possible, this way we can have 3rd party plugins written
108123
# in Python/Cython that can do things at this level
109124
r_initialization.minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE
110-
r_initialization.userdata = NULL
125+
r_initialization.userdata = NULL
111126
r_initialization.initialize = _initialize
112127
r_initialization.deinitialize = _deinitialize
113128

114129

115-
cdef void _initialize(void *userdata, GDExtensionInitializationLevel p_level):
130+
cdef void _initialize(void *userdata, GDExtensionInitializationLevel p_level) noexcept with gil:
116131
print(f'[libgodot] _initialize({p_level})', flush=True)
117132

118133
import godot._lang
119-
pythonscript_initialize = <void(*)(int)>godot._lang.pythonscript_initialize_function_ptr
134+
pythonscript_initialize = <void (*)(int)><size_t>godot._lang.pythonscript_initialize_function_ptr
120135
pythonscript_initialize(p_level);
121136

122137

123-
cdef void _deinitialize(void *userdata, GDExtensionInitializationLevel p_level):
138+
cdef void _deinitialize(void *userdata, GDExtensionInitializationLevel p_level) noexcept with gil:
124139
print(f'[libgodot] _deinitialize({p_level})', flush=True)
125140

126141
import godot._lang
127-
pythonscript_deinitialize = <void(*)(int)>godot._lang.pythonscript_deinitialize_function_ptr
142+
pythonscript_deinitialize = <void (*)(int)><size_t>godot._lang.pythonscript_deinitialize_function_ptr
128143
pythonscript_deinitialize(p_level);

uv.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)