Skip to content

Commit a7f4fa4

Browse files
committed
Add a patch for godot-cpp (#1)
To avoid singleton issue that crash when shutdown
1 parent e2b9ab3 commit a7f4fa4

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

Dev/Cpp/build.py

+7
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,20 @@ def replace_word(file_name, target_str, replace_str):
1616
with open(file_name, "w") as file:
1717
file.write(text)
1818

19+
def apply_patch():
20+
cwd = os.getcwd()
21+
os.chdir(os.path.join(os.path.dirname(script_path), "godot-cpp"))
22+
os.system("git apply ../godot-cpp.patch")
23+
os.chdir(cwd)
24+
1925
def import_generate_bindings():
2026
binding_generator = __import__("godot-cpp.binding_generator").binding_generator
2127
cwd = os.getcwd()
2228
os.chdir(os.path.join(os.path.dirname(script_path), "godot-cpp"))
2329
binding_generator.generate_bindings("gdextension/extension_api.json", False)
2430
os.chdir(cwd)
2531

32+
apply_patch()
2633
import_generate_bindings()
2734

2835
os.chdir(os.path.dirname(script_path))

Dev/Cpp/godot-cpp.patch

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
diff --git a/binding_generator.py b/binding_generator.py
2+
index 7634942..a57c93b 100644
3+
--- a/binding_generator.py
4+
+++ b/binding_generator.py
5+
@@ -1419,17 +1419,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
6+
7+
if is_singleton:
8+
result.append(f"{class_name} *{class_name}::get_singleton() {{")
9+
- result.append(f"\tconst StringName __class_name = {class_name}::get_class_static();")
10+
- result.append(
11+
- "\tstatic GDExtensionObjectPtr singleton_obj = internal::gde_interface->global_get_singleton(__class_name._native_ptr());"
12+
- )
13+
- result.append("#ifdef DEBUG_ENABLED")
14+
- result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
15+
- result.append("#endif // DEBUG_ENABLED")
16+
- result.append(
17+
- f"\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::gde_interface->object_get_instance_binding(singleton_obj, internal::token, &{class_name}::___binding_callbacks));"
18+
- )
19+
- result.append("\treturn singleton;")
20+
+ result.append(f"\tstatic SingletonBinder<{class_name}> singleton;")
21+
+ result.append("\treturn singleton.binding;")
22+
result.append("}")
23+
result.append("")
24+
25+
diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp
26+
index 17a742c..0dde2d3 100644
27+
--- a/include/godot_cpp/classes/wrapped.hpp
28+
+++ b/include/godot_cpp/classes/wrapped.hpp
29+
@@ -95,6 +95,31 @@ public:
30+
GodotObject *_owner = nullptr;
31+
};
32+
33+
+template <class T>
34+
+struct SingletonBinder {
35+
+ T *binding = nullptr;
36+
+
37+
+ SingletonBinder() {
38+
+ const StringName __class_name = T::get_class_static();
39+
+ static GDExtensionObjectPtr singleton_obj = internal::gde_interface->global_get_singleton(__class_name._native_ptr());
40+
+#ifdef DEBUG_ENABLED
41+
+ ERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);
42+
+#endif // DEBUG_ENABLED
43+
+ binding = reinterpret_cast<T *>(internal::gde_interface->object_get_instance_binding(singleton_obj, internal::token, &___binding_callbacks));
44+
+ }
45+
+
46+
+ ~SingletonBinder() {
47+
+ reinterpret_cast<T *>(binding)->~T();
48+
+ Memory::free_static(reinterpret_cast<T *>(binding));
49+
+ }
50+
+
51+
+ static constexpr GDExtensionInstanceBindingCallbacks ___binding_callbacks = {
52+
+ T::___binding_create_callback,
53+
+ nullptr, // free callback is not required
54+
+ T::___binding_reference_callback,
55+
+ };
56+
+};
57+
+
58+
} // namespace godot
59+
60+
#define GDCLASS(m_class, m_inherits) \

0 commit comments

Comments
 (0)