diff options
Diffstat (limited to 'core/extension')
-rw-r--r-- | core/extension/SCsub | 4 | ||||
-rw-r--r-- | core/extension/extension_api_dump.cpp | 311 | ||||
-rw-r--r-- | core/extension/extension_api_dump.h | 62 | ||||
-rw-r--r-- | core/extension/gdextension.cpp | 569 | ||||
-rw-r--r-- | core/extension/gdextension.h | 104 | ||||
-rw-r--r-- | core/extension/gdextension_interface.cpp | 1207 | ||||
-rw-r--r-- | core/extension/gdextension_interface.h | 643 | ||||
-rw-r--r-- | core/extension/gdextension_manager.cpp | 149 | ||||
-rw-r--r-- | core/extension/gdextension_manager.h (renamed from core/extension/native_extension_manager.h) | 86 | ||||
-rw-r--r-- | core/extension/gdnative_interface.cpp | 1074 | ||||
-rw-r--r-- | core/extension/gdnative_interface.h | 593 | ||||
-rw-r--r-- | core/extension/make_interface_dumper.py | 14 | ||||
-rw-r--r-- | core/extension/native_extension.cpp | 460 | ||||
-rw-r--r-- | core/extension/native_extension.h | 100 | ||||
-rw-r--r-- | core/extension/native_extension_manager.cpp | 149 |
15 files changed, 2966 insertions, 2559 deletions
diff --git a/core/extension/SCsub b/core/extension/SCsub index a8f68a1533..361ce43a2c 100644 --- a/core/extension/SCsub +++ b/core/extension/SCsub @@ -8,8 +8,8 @@ from platform_methods import run_in_subprocess env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", run_in_subprocess(make_wrappers.run)) env.CommandNoCache( - "gdnative_interface_dump.gen.h", - ["gdnative_interface.h", "make_interface_dumper.py"], + "gdextension_interface_dump.gen.h", + ["gdextension_interface.h", "make_interface_dumper.py"], run_in_subprocess(make_interface_dumper.run), ) diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index a2c507e350..e26ead6d8c 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* extension_api_dump.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* extension_api_dump.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "extension_api_dump.h" @@ -82,7 +82,12 @@ static String get_property_info_type_name(const PropertyInfo &p_info) { return get_builtin_or_variant_type_name(p_info.type); } -Dictionary NativeExtensionAPIDump::generate_extension_api() { +static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) { + static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" }; + return argmeta[metadata]; +} + +Dictionary GDExtensionAPIDump::generate_extension_api() { Dictionary api_dump; { @@ -177,8 +182,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { }; // Validate sizes at compile time for the current build configuration. - static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDNativeBool), "Size of bool mismatch"); - static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDNativeInt), "Size of int mismatch"); + static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDExtensionBool), "Size of bool mismatch"); + static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDExtensionInt), "Size of int mismatch"); static_assert(type_size_array[Variant::FLOAT][sizeof(void *)] == sizeof(double), "Size of float mismatch"); static_assert(type_size_array[Variant::STRING][sizeof(void *)] == sizeof(String), "Size of String mismatch"); static_assert(type_size_array[Variant::VECTOR2][sizeof(void *)] == sizeof(Vector2), "Size of Vector2 mismatch"); @@ -252,63 +257,140 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { } { - // Member offsets sizes. + // Member offsets, meta types and sizes. + +#define REAL_MEMBER_OFFSET(type, member) \ + { \ + type, \ + member, \ + "float", \ + sizeof(float), \ + "float", \ + sizeof(float), \ + "double", \ + sizeof(double), \ + "double", \ + sizeof(double), \ + } + +#define INT32_MEMBER_OFFSET(type, member) \ + { \ + type, \ + member, \ + "int32", \ + sizeof(int32_t), \ + "int32", \ + sizeof(int32_t), \ + "int32", \ + sizeof(int32_t), \ + "int32", \ + sizeof(int32_t), \ + } + +#define INT32_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \ + { \ + type, \ + member, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + member_type, \ + sizeof(int32_t) * member_elems, \ + } + +#define REAL_BASED_BUILTIN_MEMBER_OFFSET(type, member, member_type, member_elems) \ + { \ + type, \ + member, \ + member_type, \ + sizeof(float) * member_elems, \ + member_type, \ + sizeof(float) * member_elems, \ + member_type, \ + sizeof(double) * member_elems, \ + member_type, \ + sizeof(double) * member_elems, \ + } + struct { Variant::Type type; const char *member; - uint32_t offset_32_bits_real_float; - uint32_t offset_64_bits_real_float; - uint32_t offset_32_bits_real_double; - uint32_t offset_64_bits_real_double; + const char *member_meta_32_bits_real_float; + const uint32_t member_size_32_bits_real_float; + const char *member_meta_64_bits_real_float; + const uint32_t member_size_64_bits_real_float; + const char *member_meta_32_bits_real_double; + const uint32_t member_size_32_bits_real_double; + const char *member_meta_64_bits_real_double; + const uint32_t member_size_64_bits_real_double; } member_offset_array[] = { - { Variant::VECTOR2, "x", 0, 0, 0, 0 }, - { Variant::VECTOR2, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::VECTOR2I, "x", 0, 0, 0, 0 }, - { Variant::VECTOR2I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, - { Variant::RECT2, "position", 0, 0, 0, 0 }, - { Variant::RECT2, "size", 2 * sizeof(Vector2), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::RECT2I, "position", 0, 0, 0, 0 }, - { Variant::RECT2I, "size", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, - { Variant::VECTOR3, "x", 0, 0, 0, 0 }, - { Variant::VECTOR3, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::VECTOR3, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::VECTOR3I, "x", 0, 0, 0, 0 }, - { Variant::VECTOR3I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, - { Variant::VECTOR3I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, - { Variant::TRANSFORM2D, "x", 0, 0, 0, 0 }, - { Variant::TRANSFORM2D, "y", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::TRANSFORM2D, "origin", 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) }, - { Variant::VECTOR4, "x", 0, 0, 0, 0 }, - { Variant::VECTOR4, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::VECTOR4, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::VECTOR4, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) }, - { Variant::VECTOR4I, "x", 0, 0, 0, 0 }, - { Variant::VECTOR4I, "y", sizeof(int32_t), sizeof(int32_t), sizeof(int32_t), sizeof(int32_t) }, - { Variant::VECTOR4I, "z", 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) }, - { Variant::VECTOR4I, "w", 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) }, - { Variant::PLANE, "normal", 0, 0, 0, 0 }, - { Variant::PLANE, "d", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, - { Variant::QUATERNION, "x", 0, 0, 0, 0 }, - { Variant::QUATERNION, "y", sizeof(float), sizeof(float), sizeof(double), sizeof(double) }, - { Variant::QUATERNION, "z", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) }, - { Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) }, - { Variant::AABB, "position", 0, 0, 0, 0 }, - { Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, - // Remember that basis vectors are flipped! - { Variant::BASIS, "x", 0, 0, 0, 0 }, - { Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) }, - { Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) }, - { Variant::TRANSFORM3D, "basis", 0, 0, 0, 0 }, - { Variant::TRANSFORM3D, "origin", (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) }, - { Variant::PROJECTION, "x", 0, 0, 0, 0 }, - { Variant::PROJECTION, "y", vec4_elems * sizeof(float), vec4_elems * sizeof(float), vec4_elems * sizeof(double), vec4_elems * sizeof(double) }, - { Variant::PROJECTION, "z", vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(float), vec4_elems * 2 * sizeof(double), vec4_elems * 2 * sizeof(double) }, - { Variant::PROJECTION, "w", vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(float), vec4_elems * 3 * sizeof(double), vec4_elems * 3 * sizeof(double) }, - { Variant::COLOR, "r", 0, 0, 0, 0 }, - { Variant::COLOR, "g", sizeof(float), sizeof(float), sizeof(float), sizeof(float) }, - { Variant::COLOR, "b", 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(float) }, - { Variant::COLOR, "a", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(float) }, - { Variant::NIL, nullptr, 0, 0, 0, 0 }, + // Vector2 + REAL_MEMBER_OFFSET(Variant::VECTOR2, "x"), + REAL_MEMBER_OFFSET(Variant::VECTOR2, "y"), + // Vector2i + INT32_MEMBER_OFFSET(Variant::VECTOR2I, "x"), + INT32_MEMBER_OFFSET(Variant::VECTOR2I, "y"), + // Rect2 + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "position", "Vector2", 2), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2, "size", "Vector2", 2), + // Rect2i + INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "position", "Vector2i", 2), + INT32_BASED_BUILTIN_MEMBER_OFFSET(Variant::RECT2I, "size", "Vector2i", 2), + // Vector3 + REAL_MEMBER_OFFSET(Variant::VECTOR3, "x"), + REAL_MEMBER_OFFSET(Variant::VECTOR3, "y"), + REAL_MEMBER_OFFSET(Variant::VECTOR3, "z"), + // Vector3i + INT32_MEMBER_OFFSET(Variant::VECTOR3I, "x"), + INT32_MEMBER_OFFSET(Variant::VECTOR3I, "y"), + INT32_MEMBER_OFFSET(Variant::VECTOR3I, "z"), + // Transform2D + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "x", "Vector2", 2), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "y", "Vector2", 2), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM2D, "origin", "Vector2", 2), + // Vector4 + REAL_MEMBER_OFFSET(Variant::VECTOR4, "x"), + REAL_MEMBER_OFFSET(Variant::VECTOR4, "y"), + REAL_MEMBER_OFFSET(Variant::VECTOR4, "z"), + REAL_MEMBER_OFFSET(Variant::VECTOR4, "w"), + // Vector4i + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "x"), + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "y"), + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "z"), + INT32_MEMBER_OFFSET(Variant::VECTOR4I, "w"), + // Plane + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PLANE, "normal", "Vector3", vec3_elems), + REAL_MEMBER_OFFSET(Variant::PLANE, "d"), + // Quaternion + REAL_MEMBER_OFFSET(Variant::QUATERNION, "x"), + REAL_MEMBER_OFFSET(Variant::QUATERNION, "y"), + REAL_MEMBER_OFFSET(Variant::QUATERNION, "z"), + REAL_MEMBER_OFFSET(Variant::QUATERNION, "w"), + // AABB + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "position", "Vector3", vec3_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::AABB, "size", "Vector3", vec3_elems), + // Basis (remember that basis vectors are flipped!) + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "x", "Vector3", vec3_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "y", "Vector3", vec3_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::BASIS, "z", "Vector3", vec3_elems), + // Transform3D + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "basis", "Basis", vec3_elems * 3), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::TRANSFORM3D, "origin", "Vector3", vec3_elems), + // Projection + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "x", "Vector4", vec4_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "y", "Vector4", vec4_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "z", "Vector4", vec4_elems), + REAL_BASED_BUILTIN_MEMBER_OFFSET(Variant::PROJECTION, "w", "Vector4", vec4_elems), + // Color (always composed of 4bytes floats) + { Variant::COLOR, "r", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + { Variant::COLOR, "g", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + { Variant::COLOR, "b", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + { Variant::COLOR, "a", "float", sizeof(float), "float", sizeof(float), "float", sizeof(float), "float", sizeof(float) }, + // End marker, must stay last + { Variant::NIL, nullptr, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0 }, }; Array core_type_member_offsets; @@ -319,15 +401,16 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { Array type_offsets; uint32_t idx = 0; - Variant::Type last_type = Variant::NIL; + Variant::Type previous_type = Variant::NIL; Dictionary d2; Array members; + uint32_t offset = 0; while (true) { Variant::Type t = member_offset_array[idx].type; - if (t != last_type) { - if (last_type != Variant::NIL) { + if (t != previous_type) { + if (previous_type != Variant::NIL) { d2["members"] = members; type_offsets.push_back(d2); } @@ -338,27 +421,35 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t); d2 = Dictionary(); members = Array(); + offset = 0; d2["name"] = name; - last_type = t; + previous_type = t; } Dictionary d3; - uint32_t offset = 0; + const char *member_meta = nullptr; + uint32_t member_size = 0; switch (i) { case 0: - offset = member_offset_array[idx].offset_32_bits_real_float; + member_meta = member_offset_array[idx].member_meta_32_bits_real_float; + member_size = member_offset_array[idx].member_size_32_bits_real_float; break; case 1: - offset = member_offset_array[idx].offset_64_bits_real_float; + member_meta = member_offset_array[idx].member_meta_64_bits_real_float; + member_size = member_offset_array[idx].member_size_64_bits_real_float; break; case 2: - offset = member_offset_array[idx].offset_32_bits_real_double; + member_meta = member_offset_array[idx].member_meta_32_bits_real_double; + member_size = member_offset_array[idx].member_size_32_bits_real_double; break; case 3: - offset = member_offset_array[idx].offset_64_bits_real_double; + member_meta = member_offset_array[idx].member_meta_64_bits_real_double; + member_size = member_offset_array[idx].member_size_64_bits_real_double; break; } d3["member"] = member_offset_array[idx].member; d3["offset"] = offset; + d3["meta"] = member_meta; + offset += member_size; members.push_back(d3); idx++; } @@ -372,17 +463,21 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { // Global enums and constants. Array constants; HashMap<String, List<Pair<String, int64_t>>> enum_list; + HashMap<String, bool> enum_is_bitfield; for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) { int64_t value = CoreConstants::get_global_constant_value(i); String enum_name = CoreConstants::get_global_constant_enum(i); String name = CoreConstants::get_global_constant_name(i); + bool bitfield = CoreConstants::is_global_constant_bitfield(i); if (!enum_name.is_empty()) { enum_list[enum_name].push_back(Pair<String, int64_t>(name, value)); + enum_is_bitfield[enum_name] = bitfield; } else { Dictionary d; d["name"] = name; d["value"] = value; + d["is_bitfield"] = bitfield; constants.push_back(d); } } @@ -393,6 +488,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { for (const KeyValue<String, List<Pair<String, int64_t>>> &E : enum_list) { Dictionary d1; d1["name"] = E.key; + d1["is_bitfield"] = enum_is_bitfield[E.key]; Array values; for (const Pair<String, int64_t> &F : E.value) { Dictionary d2; @@ -749,6 +845,10 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { d3["type"] = get_property_info_type_name(pinfo); + if (mi.get_argument_meta(i) > 0) { + d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)mi.get_argument_meta(i)); + } + if (i == -1) { d2["return_value"] = d3; } else { @@ -793,8 +893,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { d3["type"] = get_property_info_type_name(pinfo); if (method->get_argument_meta(i) > 0) { - static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" }; - d3["meta"] = argmeta[method->get_argument_meta(i)]; + d3["meta"] = get_type_meta_name(method->get_argument_meta(i)); } if (i >= 0 && i >= (method->get_argument_count() - default_args.size())) { @@ -838,6 +937,9 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { Dictionary d3; d3["name"] = F.arguments[i].name; d3["type"] = get_property_info_type_name(F.arguments[i]); + if (F.get_argument_meta(i) > 0) { + d3["meta"] = get_type_meta_name((GodotTypeInfo::Metadata)F.get_argument_meta(i)); + } arguments.push_back(d3); } if (arguments.size()) { @@ -871,9 +973,18 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { Dictionary d2; d2["type"] = get_property_info_type_name(F); d2["name"] = String(property_name); - d2["setter"] = ClassDB::get_property_setter(class_name, F.name); - d2["getter"] = ClassDB::get_property_getter(class_name, F.name); - d2["index"] = ClassDB::get_property_index(class_name, F.name); + StringName setter = ClassDB::get_property_setter(class_name, F.name); + if (!(setter == "")) { + d2["setter"] = setter; + } + StringName getter = ClassDB::get_property_getter(class_name, F.name); + if (!(getter == "")) { + d2["getter"] = getter; + } + int index = ClassDB::get_property_index(class_name, F.name); + if (index != -1) { + d2["index"] = index; + } properties.push_back(d2); } @@ -934,7 +1045,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { return api_dump; } -void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) { +void GDExtensionAPIDump::generate_extension_json_file(const String &p_path) { Dictionary api = generate_extension_api(); Ref<JSON> json; json.instantiate(); diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h index 1bc455ea67..7e588c9446 100644 --- a/core/extension/extension_api_dump.h +++ b/core/extension/extension_api_dump.h @@ -1,41 +1,41 @@ -/*************************************************************************/ -/* extension_api_dump.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* extension_api_dump.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #ifndef EXTENSION_API_DUMP_H #define EXTENSION_API_DUMP_H -#include "core/extension/native_extension.h" +#include "core/extension/gdextension.h" #ifdef TOOLS_ENABLED -class NativeExtensionAPIDump { +class GDExtensionAPIDump { public: static Dictionary generate_extension_api(); static void generate_extension_json_file(const String &p_path); diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp new file mode 100644 index 0000000000..829e1d8e5b --- /dev/null +++ b/core/extension/gdextension.cpp @@ -0,0 +1,569 @@ +/**************************************************************************/ +/* gdextension.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gdextension.h" +#include "core/config/project_settings.h" +#include "core/io/dir_access.h" +#include "core/object/class_db.h" +#include "core/object/method_bind.h" +#include "core/os/os.h" + +String GDExtension::get_extension_list_config_file() { + return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg"); +} + +String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) { + // First, check the explicit libraries. + if (p_config->has_section("libraries")) { + List<String> libraries; + p_config->get_section_keys("libraries", &libraries); + + // Iterate the libraries, finding the best matching tags. + String best_library_path; + Vector<String> best_library_tags; + for (const String &E : libraries) { + Vector<String> tags = E.split("."); + bool all_tags_met = true; + for (int i = 0; i < tags.size(); i++) { + String tag = tags[i].strip_edges(); + if (!p_has_feature(tag)) { + all_tags_met = false; + break; + } + } + + if (all_tags_met && tags.size() > best_library_tags.size()) { + best_library_path = p_config->get_value("libraries", E); + best_library_tags = tags; + } + } + + if (!best_library_path.is_empty()) { + if (best_library_path.is_relative_path()) { + best_library_path = p_path.get_base_dir().path_join(best_library_path); + } + if (r_tags != nullptr) { + r_tags->append_array(best_library_tags); + } + return best_library_path; + } + } + + // Second, try to autodetect + String autodetect_library_prefix; + if (p_config->has_section_key("configuration", "autodetect_library_prefix")) { + autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix"); + } + if (!autodetect_library_prefix.is_empty()) { + String autodetect_path = autodetect_library_prefix; + if (autodetect_path.is_relative_path()) { + autodetect_path = p_path.get_base_dir().path_join(autodetect_path); + } + + // Find the folder and file parts of the prefix. + String folder; + String file_prefix; + if (DirAccess::dir_exists_absolute(autodetect_path)) { + folder = autodetect_path; + } else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) { + folder = autodetect_path.get_base_dir(); + file_prefix = autodetect_path.get_file(); + } else { + ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix)); + } + + // Open the folder. + Ref<DirAccess> dir = DirAccess::open(folder); + ERR_FAIL_COND_V_MSG(!dir.is_valid(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix)); + + // Iterate the files and check the prefixes, finding the best matching file. + String best_file; + Vector<String> best_file_tags; + dir->list_dir_begin(); + String file_name = dir->_get_next(); + while (file_name != "") { + if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) { + // Check if the files matches all requested feature tags. + String tags_str = file_name.trim_prefix(file_prefix); + tags_str = tags_str.trim_suffix(tags_str.get_extension()); + + Vector<String> tags = tags_str.split(".", false); + bool all_tags_met = true; + for (int i = 0; i < tags.size(); i++) { + String tag = tags[i].strip_edges(); + if (!p_has_feature(tag)) { + all_tags_met = false; + break; + } + } + + // If all tags are found in the feature list, and we found more tags than before, use this file. + if (all_tags_met && tags.size() > best_file_tags.size()) { + best_file_tags = tags; + best_file = file_name; + } + } + file_name = dir->_get_next(); + } + + if (!best_file.is_empty()) { + String library_path = folder.path_join(best_file); + if (r_tags != nullptr) { + r_tags->append_array(best_file_tags); + } + return library_path; + } + } + return String(); +} + +class GDExtensionMethodBind : public MethodBind { + GDExtensionClassMethodCall call_func; + GDExtensionClassMethodPtrCall ptrcall_func; + void *method_userdata; + bool vararg; + PropertyInfo return_value_info; + GodotTypeInfo::Metadata return_value_metadata; + List<PropertyInfo> arguments_info; + List<GodotTypeInfo::Metadata> arguments_metadata; + +protected: + virtual Variant::Type _gen_argument_type(int p_arg) const override { + if (p_arg < 0) { + return return_value_info.type; + } else { + return arguments_info[p_arg].type; + } + } + virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { + if (p_arg < 0) { + return return_value_info; + } else { + return arguments_info[p_arg]; + } + } + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { + if (p_arg < 0) { + return return_value_metadata; + } else { + return arguments_metadata[p_arg]; + } + } +#endif + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { + Variant ret; + GDExtensionClassInstancePtr extension_instance = is_static() ? nullptr : p_object->_get_extension_instance(); + GDExtensionCallError ce{ GDEXTENSION_CALL_OK, 0, 0 }; + call_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstVariantPtr *>(p_args), p_arg_count, (GDExtensionVariantPtr)&ret, &ce); + r_error.error = Callable::CallError::Error(ce.error); + r_error.argument = ce.argument; + r_error.expected = ce.expected; + return ret; + } + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { + ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug."); + GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); + ptrcall_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstTypePtr *>(p_args), (GDExtensionTypePtr)r_ret); + } + + virtual bool is_vararg() const override { + return false; + } + + explicit GDExtensionMethodBind(const GDExtensionClassMethodInfo *p_method_info) { + method_userdata = p_method_info->method_userdata; + call_func = p_method_info->call_func; + ptrcall_func = p_method_info->ptrcall_func; + set_name(*reinterpret_cast<StringName *>(p_method_info->name)); + + if (p_method_info->has_return_value) { + return_value_info = PropertyInfo(*p_method_info->return_value_info); + return_value_metadata = GodotTypeInfo::Metadata(p_method_info->return_value_metadata); + } + + for (uint32_t i = 0; i < p_method_info->argument_count; i++) { + arguments_info.push_back(PropertyInfo(p_method_info->arguments_info[i])); + arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->arguments_metadata[i])); + } + + set_hint_flags(p_method_info->method_flags); + + vararg = p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_VARARG; + _set_returns(p_method_info->has_return_value); + _set_const(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_CONST); + _set_static(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_STATIC); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(p_method_info->argument_count); +#endif + set_argument_count(p_method_info->argument_count); + + Vector<Variant> defargs; + defargs.resize(p_method_info->default_argument_count); + for (uint32_t i = 0; i < p_method_info->default_argument_count; i++) { + defargs.write[i] = *static_cast<Variant *>(p_method_info->default_arguments[i]); + } + + set_default_arguments(defargs); + } +}; + +static GDExtensionInterface gdextension_interface; + +void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name); + ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier."); + ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered."); + + Extension *parent_extension = nullptr; + + if (self->extension_classes.has(parent_class_name)) { + parent_extension = &self->extension_classes[parent_class_name]; + } else if (ClassDB::class_exists(parent_class_name)) { + if (ClassDB::get_api_type(parent_class_name) == ClassDB::API_EXTENSION || ClassDB::get_api_type(parent_class_name) == ClassDB::API_EDITOR_EXTENSION) { + ERR_PRINT("Unimplemented yet"); + //inheriting from another extension + } else { + //inheriting from engine class + } + } else { + ERR_FAIL_MSG("Attempt to register an extension class '" + String(class_name) + "' using non-existing parent class '" + String(parent_class_name) + "'"); + } + + self->extension_classes[class_name] = Extension(); + + Extension *extension = &self->extension_classes[class_name]; + + if (parent_extension) { + extension->gdextension.parent = &parent_extension->gdextension; + parent_extension->gdextension.children.push_back(&extension->gdextension); + } + + extension->gdextension.parent_class_name = parent_class_name; + extension->gdextension.class_name = class_name; + extension->gdextension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR; + extension->gdextension.is_virtual = p_extension_funcs->is_virtual; + extension->gdextension.is_abstract = p_extension_funcs->is_abstract; + extension->gdextension.set = p_extension_funcs->set_func; + extension->gdextension.get = p_extension_funcs->get_func; + extension->gdextension.get_property_list = p_extension_funcs->get_property_list_func; + extension->gdextension.free_property_list = p_extension_funcs->free_property_list_func; + extension->gdextension.property_can_revert = p_extension_funcs->property_can_revert_func; + extension->gdextension.property_get_revert = p_extension_funcs->property_get_revert_func; + extension->gdextension.notification = p_extension_funcs->notification_func; + extension->gdextension.to_string = p_extension_funcs->to_string_func; + extension->gdextension.reference = p_extension_funcs->reference_func; + extension->gdextension.unreference = p_extension_funcs->unreference_func; + extension->gdextension.class_userdata = p_extension_funcs->class_userdata; + extension->gdextension.create_instance = p_extension_funcs->create_instance_func; + extension->gdextension.free_instance = p_extension_funcs->free_instance_func; + extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func; + extension->gdextension.get_rid = p_extension_funcs->get_rid_func; + + ClassDB::register_extension_class(&extension->gdextension); +} +void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'."); + + //Extension *extension = &self->extension_classes[class_name]; + + GDExtensionMethodBind *method = memnew(GDExtensionMethodBind(p_method_info)); + method->set_instance_class(class_name); + + ClassDB::bind_method_custom(class_name, method); +} +void GDExtension::_register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name); + StringName constant_name = *reinterpret_cast<const StringName *>(p_constant_name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + constant_name + "' for unexisting class '" + class_name + "'."); + + ClassDB::bind_integer_constant(class_name, enum_name, constant_name, p_constant_value, p_is_bitfield); +} + +void GDExtension::_register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName setter = *reinterpret_cast<const StringName *>(p_setter); + StringName getter = *reinterpret_cast<const StringName *>(p_getter); + String property_name = *reinterpret_cast<const StringName *>(p_info->name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'."); + + //Extension *extension = &self->extension_classes[class_name]; + PropertyInfo pinfo(*p_info); + + ClassDB::add_property(class_name, pinfo, setter, getter); +} + +void GDExtension::_register_extension_class_property_group(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_group_name, GDExtensionConstStringPtr p_prefix) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + String group_name = *reinterpret_cast<const String *>(p_group_name); + String prefix = *reinterpret_cast<const String *>(p_prefix); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + group_name + "' for unexisting class '" + class_name + "'."); + + ClassDB::add_property_group(class_name, group_name, prefix); +} + +void GDExtension::_register_extension_class_property_subgroup(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_subgroup_name, GDExtensionConstStringPtr p_prefix) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name); + String prefix = *reinterpret_cast<const String *>(p_prefix); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + subgroup_name + "' for unexisting class '" + class_name + "'."); + + ClassDB::add_property_subgroup(class_name, subgroup_name, prefix); +} + +void GDExtension::_register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + signal_name + "' for unexisting class '" + class_name + "'."); + + MethodInfo s; + s.name = signal_name; + for (int i = 0; i < p_argument_count; i++) { + PropertyInfo arg(p_argument_info[i]); + s.arguments.push_back(arg); + } + ClassDB::add_signal(class_name, s); +} + +void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + StringName class_name = *reinterpret_cast<const StringName *>(p_class_name); + ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); + Extension *ext = &self->extension_classes[class_name]; + ERR_FAIL_COND_MSG(ext->gdextension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); + + ClassDB::unregister_extension_class(class_name); + if (ext->gdextension.parent != nullptr) { + ext->gdextension.parent->children.erase(&ext->gdextension); + } + self->extension_classes.erase(class_name); +} + +void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path) { + GDExtension *self = reinterpret_cast<GDExtension *>(p_library); + + *(String *)r_path = self->library_path; +} + +Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) { + Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true, &library_path); + if (err != OK) { + ERR_PRINT("GDExtension dynamic library not found: " + p_path); + return err; + } + + void *entry_funcptr = nullptr; + + err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false); + + if (err != OK) { + ERR_PRINT("GDExtension entry point '" + p_entry_symbol + "' not found in library " + p_path); + OS::get_singleton()->close_dynamic_library(library); + return err; + } + + GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr; + + if (initialization_function(&gdextension_interface, this, &initialization)) { + level_initialized = -1; + return OK; + } else { + ERR_PRINT("GDExtension initialization function '" + p_entry_symbol + "' returned an error."); + return FAILED; + } +} + +void GDExtension::close_library() { + ERR_FAIL_COND(library == nullptr); + OS::get_singleton()->close_dynamic_library(library); + + library = nullptr; +} + +bool GDExtension::is_library_open() const { + return library != nullptr; +} + +GDExtension::InitializationLevel GDExtension::get_minimum_library_initialization_level() const { + ERR_FAIL_COND_V(library == nullptr, INITIALIZATION_LEVEL_CORE); + return InitializationLevel(initialization.minimum_initialization_level); +} + +void GDExtension::initialize_library(InitializationLevel p_level) { + ERR_FAIL_COND(library == nullptr); + ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized)); + + level_initialized = int32_t(p_level); + + ERR_FAIL_COND(initialization.initialize == nullptr); + + initialization.initialize(initialization.userdata, GDExtensionInitializationLevel(p_level)); +} +void GDExtension::deinitialize_library(InitializationLevel p_level) { + ERR_FAIL_COND(library == nullptr); + ERR_FAIL_COND(p_level > int32_t(level_initialized)); + + level_initialized = int32_t(p_level) - 1; + initialization.deinitialize(initialization.userdata, GDExtensionInitializationLevel(p_level)); +} + +void GDExtension::_bind_methods() { + ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &GDExtension::open_library); + ClassDB::bind_method(D_METHOD("close_library"), &GDExtension::close_library); + ClassDB::bind_method(D_METHOD("is_library_open"), &GDExtension::is_library_open); + + ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &GDExtension::get_minimum_library_initialization_level); + ClassDB::bind_method(D_METHOD("initialize_library", "level"), &GDExtension::initialize_library); + + BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_CORE); + BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SERVERS); + BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SCENE); + BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR); +} + +GDExtension::GDExtension() { +} + +GDExtension::~GDExtension() { + if (library != nullptr) { + close_library(); + } +} + +extern void gdextension_setup_interface(GDExtensionInterface *p_interface); + +void GDExtension::initialize_gdextensions() { + gdextension_setup_interface(&gdextension_interface); + + gdextension_interface.classdb_register_extension_class = _register_extension_class; + gdextension_interface.classdb_register_extension_class_method = _register_extension_class_method; + gdextension_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant; + gdextension_interface.classdb_register_extension_class_property = _register_extension_class_property; + gdextension_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group; + gdextension_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup; + gdextension_interface.classdb_register_extension_class_signal = _register_extension_class_signal; + gdextension_interface.classdb_unregister_extension_class = _unregister_extension_class; + gdextension_interface.get_library_path = _get_library_path; +} + +Ref<Resource> GDExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { + Ref<ConfigFile> config; + config.instantiate(); + + Error err = config->load(p_path); + + if (r_error) { + *r_error = err; + } + + if (err != OK) { + ERR_PRINT("Error loading GDExtension configuration file: " + p_path); + return Ref<Resource>(); + } + + if (!config->has_section_key("configuration", "entry_symbol")) { + if (r_error) { + *r_error = ERR_INVALID_DATA; + } + ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path); + return Ref<Resource>(); + } + + String entry_symbol = config->get_value("configuration", "entry_symbol"); + + String library_path = GDExtension::find_extension_library(p_path, config, [](String p_feature) { return OS::get_singleton()->has_feature(p_feature); }); + + if (library_path.is_empty()) { + if (r_error) { + *r_error = ERR_FILE_NOT_FOUND; + } + const String os_arch = OS::get_singleton()->get_name().to_lower() + "." + Engine::get_singleton()->get_architecture_name(); + ERR_PRINT(vformat("No GDExtension library found for current OS and architecture (%s) in configuration file: %s", os_arch, p_path)); + return Ref<Resource>(); + } + + if (!library_path.is_resource_file() && !library_path.is_absolute_path()) { + library_path = p_path.get_base_dir().path_join(library_path); + } + + Ref<GDExtension> lib; + lib.instantiate(); + String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path); + err = lib->open_library(abs_path, entry_symbol); + + if (r_error) { + *r_error = err; + } + + if (err != OK) { + // Errors already logged in open_library() + return Ref<Resource>(); + } + + return lib; +} + +void GDExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("gdextension"); +} + +bool GDExtensionResourceLoader::handles_type(const String &p_type) const { + return p_type == "GDExtension"; +} + +String GDExtensionResourceLoader::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (el == "gdextension") { + return "GDExtension"; + } + return ""; +} diff --git a/core/extension/gdextension.h b/core/extension/gdextension.h new file mode 100644 index 0000000000..39523a142f --- /dev/null +++ b/core/extension/gdextension.h @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* gdextension.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GDEXTENSION_H +#define GDEXTENSION_H + +#include <functional> + +#include "core/extension/gdextension_interface.h" +#include "core/io/config_file.h" +#include "core/io/resource_loader.h" +#include "core/object/ref_counted.h" + +class GDExtension : public Resource { + GDCLASS(GDExtension, Resource) + + void *library = nullptr; // pointer if valid, + String library_path; + + struct Extension { + ObjectGDExtension gdextension; + }; + + HashMap<StringName, Extension> extension_classes; + + static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs); + static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info); + static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield); + static void _register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter); + static void _register_extension_class_property_group(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_group_name, GDExtensionConstStringNamePtr p_prefix); + static void _register_extension_class_property_subgroup(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_subgroup_name, GDExtensionConstStringNamePtr p_prefix); + static void _register_extension_class_signal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count); + static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); + static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path); + + GDExtensionInitialization initialization; + int32_t level_initialized = -1; + +protected: + static void _bind_methods(); + +public: + static String get_extension_list_config_file(); + static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr); + + Error open_library(const String &p_path, const String &p_entry_symbol); + void close_library(); + + enum InitializationLevel { + INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE, + INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS, + INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE, + INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR + }; + + bool is_library_open() const; + + InitializationLevel get_minimum_library_initialization_level() const; + void initialize_library(InitializationLevel p_level); + void deinitialize_library(InitializationLevel p_level); + + static void initialize_gdextensions(); + GDExtension(); + ~GDExtension(); +}; + +VARIANT_ENUM_CAST(GDExtension::InitializationLevel) + +class GDExtensionResourceLoader : public ResourceFormatLoader { +public: + virtual Ref<Resource> load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +#endif // GDEXTENSION_H diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp new file mode 100644 index 0000000000..2bedb623e4 --- /dev/null +++ b/core/extension/gdextension_interface.cpp @@ -0,0 +1,1207 @@ +/**************************************************************************/ +/* gdextension_interface.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gdextension_interface.h" + +#include "core/config/engine.h" +#include "core/io/file_access.h" +#include "core/io/xml_parser.h" +#include "core/object/class_db.h" +#include "core/object/script_language_extension.h" +#include "core/object/worker_thread_pool.h" +#include "core/os/memory.h" +#include "core/variant/variant.h" +#include "core/version.h" + +// Memory Functions +static void *gdextension_alloc(size_t p_size) { + return memalloc(p_size); +} + +static void *gdextension_realloc(void *p_mem, size_t p_size) { + return memrealloc(p_mem, p_size); +} + +static void gdextension_free(void *p_mem) { + memfree(p_mem); +} + +// Helper print functions. +static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_editor_notify, ERR_HANDLER_ERROR); +} +static void gdextension_print_error_with_message(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_message, p_editor_notify, ERR_HANDLER_ERROR); +} +static void gdextension_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_editor_notify, ERR_HANDLER_WARNING); +} +static void gdextension_print_warning_with_message(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_message, p_editor_notify, ERR_HANDLER_WARNING); +} +static void gdextension_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_editor_notify, ERR_HANDLER_SCRIPT); +} +static void gdextension_print_script_error_with_message(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) { + _err_print_error(p_function, p_file, p_line, p_description, p_message, p_editor_notify, ERR_HANDLER_SCRIPT); +} + +uint64_t gdextension_get_native_struct_size(GDExtensionConstStringNamePtr p_name) { + const StringName name = *reinterpret_cast<const StringName *>(p_name); + return ClassDB::get_native_struct_size(name); +} + +// Variant functions + +static void gdextension_variant_new_copy(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src) { + memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<const Variant *>(p_src))); +} +static void gdextension_variant_new_nil(GDExtensionVariantPtr r_dest) { + memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant); +} +static void gdextension_variant_destroy(GDExtensionVariantPtr p_self) { + reinterpret_cast<Variant *>(p_self)->~Variant(); +} + +// variant type + +static void gdextension_variant_call(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + Variant *self = (Variant *)p_self; + const StringName method = *reinterpret_cast<const StringName *>(p_method); + const Variant **args = (const Variant **)p_args; + Variant ret; + Callable::CallError error; + self->callp(method, args, p_argcount, ret, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdextension_variant_call_static(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + Variant::Type type = (Variant::Type)p_type; + const StringName method = *reinterpret_cast<const StringName *>(p_method); + const Variant **args = (const Variant **)p_args; + Variant ret; + Callable::CallError error; + Variant::call_static(type, method, args, p_argcount, ret, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)error.error; + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdextension_variant_evaluate(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid) { + Variant::Operator op = (Variant::Operator)p_op; + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + Variant *ret = (Variant *)r_return; + bool valid; + Variant::evaluate(op, *a, *b, *ret, valid); + *r_valid = valid; +} + +static void gdextension_variant_set(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) { + Variant *self = (Variant *)p_self; + const Variant *key = (const Variant *)p_key; + const Variant *value = (const Variant *)p_value; + + bool valid; + self->set(*key, *value, &valid); + *r_valid = valid; +} + +static void gdextension_variant_set_named(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) { + Variant *self = (Variant *)p_self; + const StringName *key = (const StringName *)p_key; + const Variant *value = (const Variant *)p_value; + + bool valid; + self->set_named(*key, *value, valid); + *r_valid = valid; +} + +static void gdextension_variant_set_keyed(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid) { + Variant *self = (Variant *)p_self; + const Variant *key = (const Variant *)p_key; + const Variant *value = (const Variant *)p_value; + + bool valid; + self->set_keyed(*key, *value, valid); + *r_valid = valid; +} + +static void gdextension_variant_set_indexed(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob) { + Variant *self = (Variant *)p_self; + const Variant *value = (const Variant *)p_value; + + bool valid; + bool oob; + self->set_indexed(p_index, *value, valid, oob); + *r_valid = valid; + *r_oob = oob; +} + +static void gdextension_variant_get(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const Variant *key = (const Variant *)p_key; + + bool valid; + memnew_placement(r_ret, Variant(self->get(*key, &valid))); + *r_valid = valid; +} + +static void gdextension_variant_get_named(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const StringName *key = (const StringName *)p_key; + + bool valid; + memnew_placement(r_ret, Variant(self->get_named(*key, valid))); + *r_valid = valid; +} + +static void gdextension_variant_get_keyed(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const Variant *key = (const Variant *)p_key; + + bool valid; + memnew_placement(r_ret, Variant(self->get_keyed(*key, valid))); + *r_valid = valid; +} + +static void gdextension_variant_get_indexed(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob) { + const Variant *self = (const Variant *)p_self; + + bool valid; + bool oob; + memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob))); + *r_valid = valid; + *r_oob = oob; +} + +/// Iteration. +static GDExtensionBool gdextension_variant_iter_init(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + Variant *iter = (Variant *)r_iter; + + bool valid; + bool ret = self->iter_init(*iter, valid); + *r_valid = valid; + return ret; +} + +static GDExtensionBool gdextension_variant_iter_next(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + Variant *iter = (Variant *)r_iter; + + bool valid; + bool ret = self->iter_next(*iter, valid); + *r_valid = valid; + return ret; +} + +static void gdextension_variant_iter_get(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + Variant *iter = (Variant *)r_iter; + + bool valid; + memnew_placement(r_ret, Variant(self->iter_next(*iter, valid))); + *r_valid = valid; +} + +/// Variant functions. +static GDExtensionInt gdextension_variant_hash(GDExtensionConstVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return self->hash(); +} + +static GDExtensionInt gdextension_variant_recursive_hash(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count) { + const Variant *self = (const Variant *)p_self; + return self->recursive_hash(p_recursion_count); +} + +static GDExtensionBool gdextension_variant_hash_compare(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other) { + const Variant *self = (const Variant *)p_self; + const Variant *other = (const Variant *)p_other; + return self->hash_compare(*other); +} + +static GDExtensionBool gdextension_variant_booleanize(GDExtensionConstVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return self->booleanize(); +} + +static void gdextension_variant_duplicate(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep) { + const Variant *self = (const Variant *)p_self; + memnew_placement(r_ret, Variant(self->duplicate(p_deep))); +} + +static void gdextension_variant_stringify(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret) { + const Variant *self = (const Variant *)p_self; + memnew_placement(r_ret, String(*self)); +} + +static GDExtensionVariantType gdextension_variant_get_type(GDExtensionConstVariantPtr p_self) { + const Variant *self = (const Variant *)p_self; + return (GDExtensionVariantType)self->get_type(); +} + +static GDExtensionBool gdextension_variant_has_method(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method) { + const Variant *self = (const Variant *)p_self; + const StringName *method = (const StringName *)p_method; + return self->has_method(*method); +} + +static GDExtensionBool gdextension_variant_has_member(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) { + return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member)); +} + +static GDExtensionBool gdextension_variant_has_key(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid) { + const Variant *self = (const Variant *)p_self; + const Variant *key = (const Variant *)p_key; + bool valid; + bool ret = self->has_key(*key, valid); + *r_valid = valid; + return ret; +} + +static void gdextension_variant_get_type_name(GDExtensionVariantType p_type, GDExtensionStringPtr r_ret) { + String name = Variant::get_type_name((Variant::Type)p_type); + memnew_placement(r_ret, String(name)); +} + +static GDExtensionBool gdextension_variant_can_convert(GDExtensionVariantType p_from, GDExtensionVariantType p_to) { + return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to); +} + +static GDExtensionBool gdextension_variant_can_convert_strict(GDExtensionVariantType p_from, GDExtensionVariantType p_to) { + return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to); +} + +// Variant interaction. +static GDExtensionVariantFromTypeConstructorFunc gdextension_get_variant_from_type_constructor(GDExtensionVariantType p_type) { + switch (p_type) { + case GDEXTENSION_VARIANT_TYPE_BOOL: + return VariantTypeConstructor<bool>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_INT: + return VariantTypeConstructor<int64_t>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_FLOAT: + return VariantTypeConstructor<double>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_STRING: + return VariantTypeConstructor<String>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR2: + return VariantTypeConstructor<Vector2>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR2I: + return VariantTypeConstructor<Vector2i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_RECT2: + return VariantTypeConstructor<Rect2>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_RECT2I: + return VariantTypeConstructor<Rect2i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR3: + return VariantTypeConstructor<Vector3>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR3I: + return VariantTypeConstructor<Vector3i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM2D: + return VariantTypeConstructor<Transform2D>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR4: + return VariantTypeConstructor<Vector4>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_VECTOR4I: + return VariantTypeConstructor<Vector4i>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PLANE: + return VariantTypeConstructor<Plane>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_QUATERNION: + return VariantTypeConstructor<Quaternion>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_AABB: + return VariantTypeConstructor<AABB>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_BASIS: + return VariantTypeConstructor<Basis>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM3D: + return VariantTypeConstructor<Transform3D>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PROJECTION: + return VariantTypeConstructor<Projection>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_COLOR: + return VariantTypeConstructor<Color>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_STRING_NAME: + return VariantTypeConstructor<StringName>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_NODE_PATH: + return VariantTypeConstructor<NodePath>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_RID: + return VariantTypeConstructor<RID>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_OBJECT: + return VariantTypeConstructor<Object *>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_CALLABLE: + return VariantTypeConstructor<Callable>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_SIGNAL: + return VariantTypeConstructor<Signal>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_DICTIONARY: + return VariantTypeConstructor<Dictionary>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_ARRAY: + return VariantTypeConstructor<Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY: + return VariantTypeConstructor<PackedByteArray>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY: + return VariantTypeConstructor<PackedInt32Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY: + return VariantTypeConstructor<PackedInt64Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: + return VariantTypeConstructor<PackedFloat32Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: + return VariantTypeConstructor<PackedFloat64Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY: + return VariantTypeConstructor<PackedStringArray>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: + return VariantTypeConstructor<PackedVector2Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: + return VariantTypeConstructor<PackedVector3Array>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY: + return VariantTypeConstructor<PackedColorArray>::variant_from_type; + case GDEXTENSION_VARIANT_TYPE_NIL: + case GDEXTENSION_VARIANT_TYPE_VARIANT_MAX: + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); + } + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); +} + +static GDExtensionTypeFromVariantConstructorFunc gdextension_get_type_from_variant_constructor(GDExtensionVariantType p_type) { + switch (p_type) { + case GDEXTENSION_VARIANT_TYPE_BOOL: + return VariantTypeConstructor<bool>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_INT: + return VariantTypeConstructor<int64_t>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_FLOAT: + return VariantTypeConstructor<double>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_STRING: + return VariantTypeConstructor<String>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR2: + return VariantTypeConstructor<Vector2>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR2I: + return VariantTypeConstructor<Vector2i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_RECT2: + return VariantTypeConstructor<Rect2>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_RECT2I: + return VariantTypeConstructor<Rect2i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR3: + return VariantTypeConstructor<Vector3>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR3I: + return VariantTypeConstructor<Vector3i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM2D: + return VariantTypeConstructor<Transform2D>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR4: + return VariantTypeConstructor<Vector4>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_VECTOR4I: + return VariantTypeConstructor<Vector4i>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PLANE: + return VariantTypeConstructor<Plane>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_QUATERNION: + return VariantTypeConstructor<Quaternion>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_AABB: + return VariantTypeConstructor<AABB>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_BASIS: + return VariantTypeConstructor<Basis>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_TRANSFORM3D: + return VariantTypeConstructor<Transform3D>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PROJECTION: + return VariantTypeConstructor<Projection>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_COLOR: + return VariantTypeConstructor<Color>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_STRING_NAME: + return VariantTypeConstructor<StringName>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_NODE_PATH: + return VariantTypeConstructor<NodePath>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_RID: + return VariantTypeConstructor<RID>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_OBJECT: + return VariantTypeConstructor<Object *>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_CALLABLE: + return VariantTypeConstructor<Callable>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_SIGNAL: + return VariantTypeConstructor<Signal>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_DICTIONARY: + return VariantTypeConstructor<Dictionary>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_ARRAY: + return VariantTypeConstructor<Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY: + return VariantTypeConstructor<PackedByteArray>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY: + return VariantTypeConstructor<PackedInt32Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY: + return VariantTypeConstructor<PackedInt64Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: + return VariantTypeConstructor<PackedFloat32Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: + return VariantTypeConstructor<PackedFloat64Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY: + return VariantTypeConstructor<PackedStringArray>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: + return VariantTypeConstructor<PackedVector2Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: + return VariantTypeConstructor<PackedVector3Array>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY: + return VariantTypeConstructor<PackedColorArray>::type_from_variant; + case GDEXTENSION_VARIANT_TYPE_NIL: + case GDEXTENSION_VARIANT_TYPE_VARIANT_MAX: + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); + } + ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); +} + +// ptrcalls +static GDExtensionPtrOperatorEvaluator gdextension_variant_get_ptr_operator_evaluator(GDExtensionVariantOperator p_operator, GDExtensionVariantType p_type_a, GDExtensionVariantType p_type_b) { + return (GDExtensionPtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b)); +} +static GDExtensionPtrBuiltInMethod gdextension_variant_get_ptr_builtin_method(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash) { + const StringName method = *reinterpret_cast<const StringName *>(p_method); + uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method); + if (hash != p_hash) { + ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch."); + return nullptr; + } + + return (GDExtensionPtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method); +} +static GDExtensionPtrConstructor gdextension_variant_get_ptr_constructor(GDExtensionVariantType p_type, int32_t p_constructor) { + return (GDExtensionPtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor); +} +static GDExtensionPtrDestructor gdextension_variant_get_ptr_destructor(GDExtensionVariantType p_type) { + return (GDExtensionPtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type)); +} +static void gdextension_variant_construct(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error) { + memnew_placement(p_base, Variant); + + Callable::CallError error; + Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} +static GDExtensionPtrSetter gdextension_variant_get_ptr_setter(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) { + const StringName member = *reinterpret_cast<const StringName *>(p_member); + return (GDExtensionPtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member); +} +static GDExtensionPtrGetter gdextension_variant_get_ptr_getter(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member) { + const StringName member = *reinterpret_cast<const StringName *>(p_member); + return (GDExtensionPtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member); +} +static GDExtensionPtrIndexedSetter gdextension_variant_get_ptr_indexed_setter(GDExtensionVariantType p_type) { + return (GDExtensionPtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type)); +} +static GDExtensionPtrIndexedGetter gdextension_variant_get_ptr_indexed_getter(GDExtensionVariantType p_type) { + return (GDExtensionPtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type)); +} +static GDExtensionPtrKeyedSetter gdextension_variant_get_ptr_keyed_setter(GDExtensionVariantType p_type) { + return (GDExtensionPtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type)); +} +static GDExtensionPtrKeyedGetter gdextension_variant_get_ptr_keyed_getter(GDExtensionVariantType p_type) { + return (GDExtensionPtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type)); +} +static GDExtensionPtrKeyedChecker gdextension_variant_get_ptr_keyed_checker(GDExtensionVariantType p_type) { + return (GDExtensionPtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type)); +} +static void gdextension_variant_get_constant_value(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret) { + StringName constant = *reinterpret_cast<const StringName *>(p_constant); + memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant))); +} +static GDExtensionPtrUtilityFunction gdextension_variant_get_ptr_utility_function(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash) { + StringName function = *reinterpret_cast<const StringName *>(p_function); + uint32_t hash = Variant::get_utility_function_hash(function); + if (hash != p_hash) { + ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch."); + return nullptr; + } + return (GDExtensionPtrUtilityFunction)Variant::get_ptr_utility_function(function); +} + +//string helpers + +static void gdextension_string_new_with_latin1_chars(GDExtensionStringPtr r_dest, const char *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String(p_contents); +} + +static void gdextension_string_new_with_utf8_chars(GDExtensionStringPtr r_dest, const char *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf8(p_contents); +} + +static void gdextension_string_new_with_utf16_chars(GDExtensionStringPtr r_dest, const char16_t *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf16(p_contents); +} + +static void gdextension_string_new_with_utf32_chars(GDExtensionStringPtr r_dest, const char32_t *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents); +} + +static void gdextension_string_new_with_wide_chars(GDExtensionStringPtr r_dest, const wchar_t *p_contents) { + String *dest = (String *)r_dest; + if constexpr (sizeof(wchar_t) == 2) { + // wchar_t is 16 bit, parse. + memnew_placement(dest, String); + dest->parse_utf16((const char16_t *)p_contents); + } else { + // wchar_t is 32 bit, copy. + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents); + } +} + +static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String(p_contents, p_size); +} + +static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf8(p_contents, p_size); +} + +static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf16(p_contents, p_size); +} + +static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents, p_size); +} + +static void gdextension_string_new_with_wide_chars_and_len(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size) { + String *dest = (String *)r_dest; + if constexpr (sizeof(wchar_t) == 2) { + // wchar_t is 16 bit, parse. + memnew_placement(dest, String); + dest->parse_utf16((const char16_t *)p_contents, p_size); + } else { + // wchar_t is 32 bit, copy. + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents, p_size); + } +} + +static GDExtensionInt gdextension_string_to_latin1_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + CharString cs = self->ascii(true); + GDExtensionInt len = cs.length(); + if (r_text) { + const char *s_text = cs.ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_utf8_chars(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + CharString cs = self->utf8(); + GDExtensionInt len = cs.length(); + if (r_text) { + const char *s_text = cs.ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_utf16_chars(GDExtensionConstStringPtr p_self, char16_t *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + Char16String cs = self->utf16(); + GDExtensionInt len = cs.length(); + if (r_text) { + const char16_t *s_text = cs.ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_utf32_chars(GDExtensionConstStringPtr p_self, char32_t *r_text, GDExtensionInt p_max_write_length) { + String *self = (String *)p_self; + GDExtensionInt len = self->length(); + if (r_text) { + const char32_t *s_text = self->ptr(); + for (GDExtensionInt i = 0; i < MIN(len, p_max_write_length); i++) { + r_text[i] = s_text[i]; + } + } + return len; +} +static GDExtensionInt gdextension_string_to_wide_chars(GDExtensionConstStringPtr p_self, wchar_t *r_text, GDExtensionInt p_max_write_length) { + if constexpr (sizeof(wchar_t) == 4) { + return gdextension_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length); + } else { + return gdextension_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length); + } +} + +static char32_t *gdextension_string_operator_index(GDExtensionStringPtr p_self, GDExtensionInt p_index) { + String *self = (String *)p_self; + ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); + return &self->ptrw()[p_index]; +} + +static const char32_t *gdextension_string_operator_index_const(GDExtensionConstStringPtr p_self, GDExtensionInt p_index) { + const String *self = (const String *)p_self; + ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); + return &self->ptr()[p_index]; +} + +static void gdextension_string_operator_plus_eq_string(GDExtensionStringPtr p_self, GDExtensionConstStringPtr p_b) { + String *self = (String *)p_self; + const String *b = (const String *)p_b; + *self += *b; +} + +static void gdextension_string_operator_plus_eq_char(GDExtensionStringPtr p_self, char32_t p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static void gdextension_string_operator_plus_eq_cstr(GDExtensionStringPtr p_self, const char *p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static void gdextension_string_operator_plus_eq_wcstr(GDExtensionStringPtr p_self, const wchar_t *p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static void gdextension_string_operator_plus_eq_c32str(GDExtensionStringPtr p_self, const char32_t *p_b) { + String *self = (String *)p_self; + *self += p_b; +} + +static GDExtensionInt gdextension_xml_parser_open_buffer(GDExtensionObjectPtr p_instance, const uint8_t *p_buffer, size_t p_size) { + XMLParser *xml = (XMLParser *)p_instance; + return (GDExtensionInt)xml->_open_buffer(p_buffer, p_size); +} + +static void gdextension_file_access_store_buffer(GDExtensionObjectPtr p_instance, const uint8_t *p_src, uint64_t p_length) { + FileAccess *fa = (FileAccess *)p_instance; + fa->store_buffer(p_src, p_length); +} + +static uint64_t gdextension_file_access_get_buffer(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length) { + const FileAccess *fa = (FileAccess *)p_instance; + return fa->get_buffer(p_dst, p_length); +} + +static int64_t gdextension_worker_thread_pool_add_native_group_task(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description) { + WorkerThreadPool *p = (WorkerThreadPool *)p_instance; + const String *description = (const String *)p_description; + return (int64_t)p->add_native_group_task(p_func, p_userdata, p_elements, p_tasks, static_cast<bool>(p_high_priority), *description); +} + +static int64_t gdextension_worker_thread_pool_add_native_task(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description) { + WorkerThreadPool *p = (WorkerThreadPool *)p_instance; + const String *description = (const String *)p_description; + return (int64_t)p->add_native_task(p_func, p_userdata, static_cast<bool>(p_high_priority), *description); +} + +/* Packed array functions */ + +static uint8_t *gdextension_packed_byte_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedByteArray *self = (PackedByteArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const uint8_t *gdextension_packed_byte_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedByteArray *self = (const PackedByteArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_color_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedColorArray *self = (PackedColorArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_color_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedColorArray *self = (const PackedColorArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + +static float *gdextension_packed_float32_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedFloat32Array *self = (PackedFloat32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const float *gdextension_packed_float32_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedFloat32Array *self = (const PackedFloat32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static double *gdextension_packed_float64_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedFloat64Array *self = (PackedFloat64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const double *gdextension_packed_float64_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedFloat64Array *self = (const PackedFloat64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static int32_t *gdextension_packed_int32_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedInt32Array *self = (PackedInt32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const int32_t *gdextension_packed_int32_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedInt32Array *self = (const PackedInt32Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static int64_t *gdextension_packed_int64_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedInt64Array *self = (PackedInt64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptrw()[p_index]; +} + +static const int64_t *gdextension_packed_int64_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedInt64Array *self = (const PackedInt64Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return &self->ptr()[p_index]; +} + +static GDExtensionStringPtr gdextension_packed_string_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedStringArray *self = (PackedStringArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionStringPtr)&self->ptrw()[p_index]; +} + +static GDExtensionStringPtr gdextension_packed_string_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedStringArray *self = (const PackedStringArray *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionStringPtr)&self->ptr()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector2_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedVector2Array *self = (PackedVector2Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector2_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedVector2Array *self = (const PackedVector2Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + PackedVector3Array *self = (PackedVector3Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptrw()[p_index]; +} + +static GDExtensionTypePtr gdextension_packed_vector3_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const PackedVector3Array *self = (const PackedVector3Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionTypePtr)&self->ptr()[p_index]; +} + +static GDExtensionVariantPtr gdextension_array_operator_index(GDExtensionTypePtr p_self, GDExtensionInt p_index) { + Array *self = (Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionVariantPtr)&self->operator[](p_index); +} + +static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionInt p_index) { + const Array *self = (const Array *)p_self; + ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); + return (GDExtensionVariantPtr)&self->operator[](p_index); +} + +void gdextension_array_ref(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from) { + Array *self = (Array *)p_self; + const Array *from = (const Array *)p_from; + self->_ref(*from); +} + +void gdextension_array_set_typed(GDExtensionTypePtr p_self, GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script) { + Array *self = reinterpret_cast<Array *>(p_self); + const StringName *class_name = reinterpret_cast<const StringName *>(p_class_name); + const Variant *script = reinterpret_cast<const Variant *>(p_script); + self->set_typed((uint32_t)p_type, *class_name, *script); +} + +/* Dictionary functions */ + +static GDExtensionVariantPtr gdextension_dictionary_operator_index(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key) { + Dictionary *self = (Dictionary *)p_self; + return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key); +} + +static GDExtensionVariantPtr gdextension_dictionary_operator_index_const(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key) { + const Dictionary *self = (const Dictionary *)p_self; + return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key); +} + +/* OBJECT API */ + +static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { + const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind); + Object *o = (Object *)p_instance; + const Variant **args = (const Variant **)p_args; + Callable::CallError error; + + Variant ret = mb->call(o, args, p_arg_count, error); + memnew_placement(r_return, Variant(ret)); + + if (r_error) { + r_error->error = (GDExtensionCallErrorType)(error.error); + r_error->argument = error.argument; + r_error->expected = error.expected; + } +} + +static void gdextension_object_method_bind_ptrcall(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) { + const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind); + Object *o = (Object *)p_instance; + mb->ptrcall(o, (const void **)p_args, p_ret); +} + +static void gdextension_object_destroy(GDExtensionObjectPtr p_o) { + memdelete((Object *)p_o); +} + +static GDExtensionObjectPtr gdextension_global_get_singleton(GDExtensionConstStringNamePtr p_name) { + const StringName name = *reinterpret_cast<const StringName *>(p_name); + return (GDExtensionObjectPtr)Engine::get_singleton()->get_singleton_object(name); +} + +static void *gdextension_object_get_instance_binding(GDExtensionObjectPtr p_object, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + Object *o = (Object *)p_object; + return o->get_instance_binding(p_token, p_callbacks); +} + +static void gdextension_object_set_instance_binding(GDExtensionObjectPtr p_object, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + Object *o = (Object *)p_object; + o->set_instance_binding(p_token, p_binding, p_callbacks); +} + +static void gdextension_object_set_instance(GDExtensionObjectPtr p_object, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + Object *o = (Object *)p_object; + ClassDB::set_object_extension_instance(o, classname, p_instance); +} + +static GDExtensionObjectPtr gdextension_object_get_instance_from_id(GDObjectInstanceID p_instance_id) { + return (GDExtensionObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id)); +} + +static GDExtensionObjectPtr gdextension_object_cast_to(GDExtensionConstObjectPtr p_object, void *p_class_tag) { + if (!p_object) { + return nullptr; + } + Object *o = (Object *)p_object; + + return o->is_class_ptr(p_class_tag) ? (GDExtensionObjectPtr)o : (GDExtensionObjectPtr) nullptr; +} + +static GDObjectInstanceID gdextension_object_get_instance_id(GDExtensionConstObjectPtr p_object) { + const Object *o = (const Object *)p_object; + return (GDObjectInstanceID)o->get_instance_id(); +} + +static GDExtensionObjectPtr gdextension_ref_get_object(GDExtensionConstRefPtr p_ref) { + const Ref<RefCounted> *ref = (const Ref<RefCounted> *)p_ref; + if (ref == nullptr || ref->is_null()) { + return (GDExtensionObjectPtr) nullptr; + } else { + return (GDExtensionObjectPtr)ref->ptr(); + } +} + +static void gdextension_ref_set_object(GDExtensionRefPtr p_ref, GDExtensionObjectPtr p_object) { + Ref<RefCounted> *ref = (Ref<RefCounted> *)p_ref; + ERR_FAIL_NULL(ref); + + Object *o = (RefCounted *)p_object; + ref->reference_ptr(o); +} + +static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data) { + ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension); + script_instance_extension->instance = p_instance_data; + script_instance_extension->native_info = p_info; + return reinterpret_cast<GDExtensionScriptInstancePtr>(script_instance_extension); +} + +static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionConstStringNamePtr p_classname, GDExtensionConstStringNamePtr p_methodname, GDExtensionInt p_hash) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname); + MethodBind *mb = ClassDB::get_method(classname, methodname); + ERR_FAIL_COND_V(!mb, nullptr); + if (mb->get_hash() != p_hash) { + ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'."); + return nullptr; + } + return (GDExtensionMethodBindPtr)mb; +} + +static GDExtensionObjectPtr gdextension_classdb_construct_object(GDExtensionConstStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + return (GDExtensionObjectPtr)ClassDB::instantiate(classname); +} + +static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_classname) { + const StringName classname = *reinterpret_cast<const StringName *>(p_classname); + ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname); + return class_info ? class_info->class_ptr : nullptr; +} + +void gdextension_setup_interface(GDExtensionInterface *p_interface) { + GDExtensionInterface &gde_interface = *p_interface; + + gde_interface.version_major = VERSION_MAJOR; + gde_interface.version_minor = VERSION_MINOR; +#if VERSION_PATCH + gde_interface.version_patch = VERSION_PATCH; +#else + gde_interface.version_patch = 0; +#endif + gde_interface.version_string = VERSION_FULL_NAME; + + /* GODOT CORE */ + + gde_interface.mem_alloc = gdextension_alloc; + gde_interface.mem_realloc = gdextension_realloc; + gde_interface.mem_free = gdextension_free; + + gde_interface.print_error = gdextension_print_error; + gde_interface.print_error_with_message = gdextension_print_error_with_message; + gde_interface.print_warning = gdextension_print_warning; + gde_interface.print_warning_with_message = gdextension_print_warning_with_message; + gde_interface.print_script_error = gdextension_print_script_error; + gde_interface.print_script_error_with_message = gdextension_print_script_error_with_message; + + gde_interface.get_native_struct_size = gdextension_get_native_struct_size; + + /* GODOT VARIANT */ + + // variant general + gde_interface.variant_new_copy = gdextension_variant_new_copy; + gde_interface.variant_new_nil = gdextension_variant_new_nil; + gde_interface.variant_destroy = gdextension_variant_destroy; + + gde_interface.variant_call = gdextension_variant_call; + gde_interface.variant_call_static = gdextension_variant_call_static; + gde_interface.variant_evaluate = gdextension_variant_evaluate; + gde_interface.variant_set = gdextension_variant_set; + gde_interface.variant_set_named = gdextension_variant_set_named; + gde_interface.variant_set_keyed = gdextension_variant_set_keyed; + gde_interface.variant_set_indexed = gdextension_variant_set_indexed; + gde_interface.variant_get = gdextension_variant_get; + gde_interface.variant_get_named = gdextension_variant_get_named; + gde_interface.variant_get_keyed = gdextension_variant_get_keyed; + gde_interface.variant_get_indexed = gdextension_variant_get_indexed; + gde_interface.variant_iter_init = gdextension_variant_iter_init; + gde_interface.variant_iter_next = gdextension_variant_iter_next; + gde_interface.variant_iter_get = gdextension_variant_iter_get; + gde_interface.variant_hash = gdextension_variant_hash; + gde_interface.variant_recursive_hash = gdextension_variant_recursive_hash; + gde_interface.variant_hash_compare = gdextension_variant_hash_compare; + gde_interface.variant_booleanize = gdextension_variant_booleanize; + gde_interface.variant_duplicate = gdextension_variant_duplicate; + gde_interface.variant_stringify = gdextension_variant_stringify; + + gde_interface.variant_get_type = gdextension_variant_get_type; + gde_interface.variant_has_method = gdextension_variant_has_method; + gde_interface.variant_has_member = gdextension_variant_has_member; + gde_interface.variant_has_key = gdextension_variant_has_key; + gde_interface.variant_get_type_name = gdextension_variant_get_type_name; + gde_interface.variant_can_convert = gdextension_variant_can_convert; + gde_interface.variant_can_convert_strict = gdextension_variant_can_convert_strict; + + gde_interface.get_variant_from_type_constructor = gdextension_get_variant_from_type_constructor; + gde_interface.get_variant_to_type_constructor = gdextension_get_type_from_variant_constructor; + + // ptrcalls. + + gde_interface.variant_get_ptr_operator_evaluator = gdextension_variant_get_ptr_operator_evaluator; + gde_interface.variant_get_ptr_builtin_method = gdextension_variant_get_ptr_builtin_method; + gde_interface.variant_get_ptr_constructor = gdextension_variant_get_ptr_constructor; + gde_interface.variant_get_ptr_destructor = gdextension_variant_get_ptr_destructor; + gde_interface.variant_construct = gdextension_variant_construct; + gde_interface.variant_get_ptr_setter = gdextension_variant_get_ptr_setter; + gde_interface.variant_get_ptr_getter = gdextension_variant_get_ptr_getter; + gde_interface.variant_get_ptr_indexed_setter = gdextension_variant_get_ptr_indexed_setter; + gde_interface.variant_get_ptr_indexed_getter = gdextension_variant_get_ptr_indexed_getter; + gde_interface.variant_get_ptr_keyed_setter = gdextension_variant_get_ptr_keyed_setter; + gde_interface.variant_get_ptr_keyed_getter = gdextension_variant_get_ptr_keyed_getter; + gde_interface.variant_get_ptr_keyed_checker = gdextension_variant_get_ptr_keyed_checker; + gde_interface.variant_get_constant_value = gdextension_variant_get_constant_value; + gde_interface.variant_get_ptr_utility_function = gdextension_variant_get_ptr_utility_function; + + // extra utilities + + gde_interface.string_new_with_latin1_chars = gdextension_string_new_with_latin1_chars; + gde_interface.string_new_with_utf8_chars = gdextension_string_new_with_utf8_chars; + gde_interface.string_new_with_utf16_chars = gdextension_string_new_with_utf16_chars; + gde_interface.string_new_with_utf32_chars = gdextension_string_new_with_utf32_chars; + gde_interface.string_new_with_wide_chars = gdextension_string_new_with_wide_chars; + gde_interface.string_new_with_latin1_chars_and_len = gdextension_string_new_with_latin1_chars_and_len; + gde_interface.string_new_with_utf8_chars_and_len = gdextension_string_new_with_utf8_chars_and_len; + gde_interface.string_new_with_utf16_chars_and_len = gdextension_string_new_with_utf16_chars_and_len; + gde_interface.string_new_with_utf32_chars_and_len = gdextension_string_new_with_utf32_chars_and_len; + gde_interface.string_new_with_wide_chars_and_len = gdextension_string_new_with_wide_chars_and_len; + gde_interface.string_to_latin1_chars = gdextension_string_to_latin1_chars; + gde_interface.string_to_utf8_chars = gdextension_string_to_utf8_chars; + gde_interface.string_to_utf16_chars = gdextension_string_to_utf16_chars; + gde_interface.string_to_utf32_chars = gdextension_string_to_utf32_chars; + gde_interface.string_to_wide_chars = gdextension_string_to_wide_chars; + gde_interface.string_operator_index = gdextension_string_operator_index; + gde_interface.string_operator_index_const = gdextension_string_operator_index_const; + gde_interface.string_operator_plus_eq_string = gdextension_string_operator_plus_eq_string; + gde_interface.string_operator_plus_eq_char = gdextension_string_operator_plus_eq_char; + gde_interface.string_operator_plus_eq_cstr = gdextension_string_operator_plus_eq_cstr; + gde_interface.string_operator_plus_eq_wcstr = gdextension_string_operator_plus_eq_wcstr; + gde_interface.string_operator_plus_eq_c32str = gdextension_string_operator_plus_eq_c32str; + + /* XMLParser extra utilities */ + + gde_interface.xml_parser_open_buffer = gdextension_xml_parser_open_buffer; + + /* FileAccess extra utilities */ + + gde_interface.file_access_store_buffer = gdextension_file_access_store_buffer; + gde_interface.file_access_get_buffer = gdextension_file_access_get_buffer; + + /* WorkerThreadPool extra utilities */ + + gde_interface.worker_thread_pool_add_native_group_task = gdextension_worker_thread_pool_add_native_group_task; + gde_interface.worker_thread_pool_add_native_task = gdextension_worker_thread_pool_add_native_task; + + /* Packed array functions */ + + gde_interface.packed_byte_array_operator_index = gdextension_packed_byte_array_operator_index; + gde_interface.packed_byte_array_operator_index_const = gdextension_packed_byte_array_operator_index_const; + + gde_interface.packed_color_array_operator_index = gdextension_packed_color_array_operator_index; + gde_interface.packed_color_array_operator_index_const = gdextension_packed_color_array_operator_index_const; + + gde_interface.packed_float32_array_operator_index = gdextension_packed_float32_array_operator_index; + gde_interface.packed_float32_array_operator_index_const = gdextension_packed_float32_array_operator_index_const; + gde_interface.packed_float64_array_operator_index = gdextension_packed_float64_array_operator_index; + gde_interface.packed_float64_array_operator_index_const = gdextension_packed_float64_array_operator_index_const; + + gde_interface.packed_int32_array_operator_index = gdextension_packed_int32_array_operator_index; + gde_interface.packed_int32_array_operator_index_const = gdextension_packed_int32_array_operator_index_const; + gde_interface.packed_int64_array_operator_index = gdextension_packed_int64_array_operator_index; + gde_interface.packed_int64_array_operator_index_const = gdextension_packed_int64_array_operator_index_const; + + gde_interface.packed_string_array_operator_index = gdextension_packed_string_array_operator_index; + gde_interface.packed_string_array_operator_index_const = gdextension_packed_string_array_operator_index_const; + + gde_interface.packed_vector2_array_operator_index = gdextension_packed_vector2_array_operator_index; + gde_interface.packed_vector2_array_operator_index_const = gdextension_packed_vector2_array_operator_index_const; + gde_interface.packed_vector3_array_operator_index = gdextension_packed_vector3_array_operator_index; + gde_interface.packed_vector3_array_operator_index_const = gdextension_packed_vector3_array_operator_index_const; + + gde_interface.array_operator_index = gdextension_array_operator_index; + gde_interface.array_operator_index_const = gdextension_array_operator_index_const; + gde_interface.array_ref = gdextension_array_ref; + gde_interface.array_set_typed = gdextension_array_set_typed; + + /* Dictionary functions */ + + gde_interface.dictionary_operator_index = gdextension_dictionary_operator_index; + gde_interface.dictionary_operator_index_const = gdextension_dictionary_operator_index_const; + + /* OBJECT */ + + gde_interface.object_method_bind_call = gdextension_object_method_bind_call; + gde_interface.object_method_bind_ptrcall = gdextension_object_method_bind_ptrcall; + gde_interface.object_destroy = gdextension_object_destroy; + gde_interface.global_get_singleton = gdextension_global_get_singleton; + gde_interface.object_get_instance_binding = gdextension_object_get_instance_binding; + gde_interface.object_set_instance_binding = gdextension_object_set_instance_binding; + gde_interface.object_set_instance = gdextension_object_set_instance; + + gde_interface.object_cast_to = gdextension_object_cast_to; + gde_interface.object_get_instance_from_id = gdextension_object_get_instance_from_id; + gde_interface.object_get_instance_id = gdextension_object_get_instance_id; + + /* REFERENCE */ + + gde_interface.ref_get_object = gdextension_ref_get_object; + gde_interface.ref_set_object = gdextension_ref_set_object; + + /* SCRIPT INSTANCE */ + + gde_interface.script_instance_create = gdextension_script_instance_create; + + /* CLASSDB */ + + gde_interface.classdb_construct_object = gdextension_classdb_construct_object; + gde_interface.classdb_get_method_bind = gdextension_classdb_get_method_bind; + gde_interface.classdb_get_class_tag = gdextension_classdb_get_class_tag; + + /* CLASSDB EXTENSION */ + + //these are filled by implementation, since it will want to keep track of registered classes + gde_interface.classdb_register_extension_class = nullptr; + gde_interface.classdb_register_extension_class_method = nullptr; + gde_interface.classdb_register_extension_class_integer_constant = nullptr; + gde_interface.classdb_register_extension_class_property = nullptr; + gde_interface.classdb_register_extension_class_property_group = nullptr; + gde_interface.classdb_register_extension_class_property_subgroup = nullptr; + gde_interface.classdb_register_extension_class_signal = nullptr; + gde_interface.classdb_unregister_extension_class = nullptr; + + gde_interface.get_library_path = nullptr; +} diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h new file mode 100644 index 0000000000..f323b2aa53 --- /dev/null +++ b/core/extension/gdextension_interface.h @@ -0,0 +1,643 @@ +/**************************************************************************/ +/* gdextension_interface.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GDEXTENSION_INTERFACE_H +#define GDEXTENSION_INTERFACE_H + +/* This is a C class header, you can copy it and use it directly in your own binders. + * Together with the JSON file, you should be able to generate any binder. + */ + +#include <stddef.h> +#include <stdint.h> + +#ifndef __cplusplus +typedef uint32_t char32_t; +typedef uint16_t char16_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* VARIANT TYPES */ + +typedef enum { + GDEXTENSION_VARIANT_TYPE_NIL, + + /* atomic types */ + GDEXTENSION_VARIANT_TYPE_BOOL, + GDEXTENSION_VARIANT_TYPE_INT, + GDEXTENSION_VARIANT_TYPE_FLOAT, + GDEXTENSION_VARIANT_TYPE_STRING, + + /* math types */ + GDEXTENSION_VARIANT_TYPE_VECTOR2, + GDEXTENSION_VARIANT_TYPE_VECTOR2I, + GDEXTENSION_VARIANT_TYPE_RECT2, + GDEXTENSION_VARIANT_TYPE_RECT2I, + GDEXTENSION_VARIANT_TYPE_VECTOR3, + GDEXTENSION_VARIANT_TYPE_VECTOR3I, + GDEXTENSION_VARIANT_TYPE_TRANSFORM2D, + GDEXTENSION_VARIANT_TYPE_VECTOR4, + GDEXTENSION_VARIANT_TYPE_VECTOR4I, + GDEXTENSION_VARIANT_TYPE_PLANE, + GDEXTENSION_VARIANT_TYPE_QUATERNION, + GDEXTENSION_VARIANT_TYPE_AABB, + GDEXTENSION_VARIANT_TYPE_BASIS, + GDEXTENSION_VARIANT_TYPE_TRANSFORM3D, + GDEXTENSION_VARIANT_TYPE_PROJECTION, + + /* misc types */ + GDEXTENSION_VARIANT_TYPE_COLOR, + GDEXTENSION_VARIANT_TYPE_STRING_NAME, + GDEXTENSION_VARIANT_TYPE_NODE_PATH, + GDEXTENSION_VARIANT_TYPE_RID, + GDEXTENSION_VARIANT_TYPE_OBJECT, + GDEXTENSION_VARIANT_TYPE_CALLABLE, + GDEXTENSION_VARIANT_TYPE_SIGNAL, + GDEXTENSION_VARIANT_TYPE_DICTIONARY, + GDEXTENSION_VARIANT_TYPE_ARRAY, + + /* typed arrays */ + GDEXTENSION_VARIANT_TYPE_PACKED_BYTE_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_INT32_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_INT64_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT32_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_FLOAT64_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_STRING_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR2_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, + GDEXTENSION_VARIANT_TYPE_PACKED_COLOR_ARRAY, + + GDEXTENSION_VARIANT_TYPE_VARIANT_MAX +} GDExtensionVariantType; + +typedef enum { + /* comparison */ + GDEXTENSION_VARIANT_OP_EQUAL, + GDEXTENSION_VARIANT_OP_NOT_EQUAL, + GDEXTENSION_VARIANT_OP_LESS, + GDEXTENSION_VARIANT_OP_LESS_EQUAL, + GDEXTENSION_VARIANT_OP_GREATER, + GDEXTENSION_VARIANT_OP_GREATER_EQUAL, + + /* mathematic */ + GDEXTENSION_VARIANT_OP_ADD, + GDEXTENSION_VARIANT_OP_SUBTRACT, + GDEXTENSION_VARIANT_OP_MULTIPLY, + GDEXTENSION_VARIANT_OP_DIVIDE, + GDEXTENSION_VARIANT_OP_NEGATE, + GDEXTENSION_VARIANT_OP_POSITIVE, + GDEXTENSION_VARIANT_OP_MODULE, + GDEXTENSION_VARIANT_OP_POWER, + + /* bitwise */ + GDEXTENSION_VARIANT_OP_SHIFT_LEFT, + GDEXTENSION_VARIANT_OP_SHIFT_RIGHT, + GDEXTENSION_VARIANT_OP_BIT_AND, + GDEXTENSION_VARIANT_OP_BIT_OR, + GDEXTENSION_VARIANT_OP_BIT_XOR, + GDEXTENSION_VARIANT_OP_BIT_NEGATE, + + /* logic */ + GDEXTENSION_VARIANT_OP_AND, + GDEXTENSION_VARIANT_OP_OR, + GDEXTENSION_VARIANT_OP_XOR, + GDEXTENSION_VARIANT_OP_NOT, + + /* containment */ + GDEXTENSION_VARIANT_OP_IN, + GDEXTENSION_VARIANT_OP_MAX + +} GDExtensionVariantOperator; + +typedef void *GDExtensionVariantPtr; +typedef const void *GDExtensionConstVariantPtr; +typedef void *GDExtensionStringNamePtr; +typedef const void *GDExtensionConstStringNamePtr; +typedef void *GDExtensionStringPtr; +typedef const void *GDExtensionConstStringPtr; +typedef void *GDExtensionObjectPtr; +typedef const void *GDExtensionConstObjectPtr; +typedef void *GDExtensionTypePtr; +typedef const void *GDExtensionConstTypePtr; +typedef const void *GDExtensionMethodBindPtr; +typedef int64_t GDExtensionInt; +typedef uint8_t GDExtensionBool; +typedef uint64_t GDObjectInstanceID; +typedef void *GDExtensionRefPtr; +typedef const void *GDExtensionConstRefPtr; + +/* VARIANT DATA I/O */ + +typedef enum { + GDEXTENSION_CALL_OK, + GDEXTENSION_CALL_ERROR_INVALID_METHOD, + GDEXTENSION_CALL_ERROR_INVALID_ARGUMENT, // Expected a different variant type. + GDEXTENSION_CALL_ERROR_TOO_MANY_ARGUMENTS, // Expected lower number of arguments. + GDEXTENSION_CALL_ERROR_TOO_FEW_ARGUMENTS, // Expected higher number of arguments. + GDEXTENSION_CALL_ERROR_INSTANCE_IS_NULL, + GDEXTENSION_CALL_ERROR_METHOD_NOT_CONST, // Used for const call. +} GDExtensionCallErrorType; + +typedef struct { + GDExtensionCallErrorType error; + int32_t argument; + int32_t expected; +} GDExtensionCallError; + +typedef void (*GDExtensionVariantFromTypeConstructorFunc)(GDExtensionVariantPtr, GDExtensionTypePtr); +typedef void (*GDExtensionTypeFromVariantConstructorFunc)(GDExtensionTypePtr, GDExtensionVariantPtr); +typedef void (*GDExtensionPtrOperatorEvaluator)(GDExtensionConstTypePtr p_left, GDExtensionConstTypePtr p_right, GDExtensionTypePtr r_result); +typedef void (*GDExtensionPtrBuiltInMethod)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return, int p_argument_count); +typedef void (*GDExtensionPtrConstructor)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args); +typedef void (*GDExtensionPtrDestructor)(GDExtensionTypePtr p_base); +typedef void (*GDExtensionPtrSetter)(GDExtensionTypePtr p_base, GDExtensionConstTypePtr p_value); +typedef void (*GDExtensionPtrGetter)(GDExtensionConstTypePtr p_base, GDExtensionTypePtr r_value); +typedef void (*GDExtensionPtrIndexedSetter)(GDExtensionTypePtr p_base, GDExtensionInt p_index, GDExtensionConstTypePtr p_value); +typedef void (*GDExtensionPtrIndexedGetter)(GDExtensionConstTypePtr p_base, GDExtensionInt p_index, GDExtensionTypePtr r_value); +typedef void (*GDExtensionPtrKeyedSetter)(GDExtensionTypePtr p_base, GDExtensionConstTypePtr p_key, GDExtensionConstTypePtr p_value); +typedef void (*GDExtensionPtrKeyedGetter)(GDExtensionConstTypePtr p_base, GDExtensionConstTypePtr p_key, GDExtensionTypePtr r_value); +typedef uint32_t (*GDExtensionPtrKeyedChecker)(GDExtensionConstVariantPtr p_base, GDExtensionConstVariantPtr p_key); +typedef void (*GDExtensionPtrUtilityFunction)(GDExtensionTypePtr r_return, const GDExtensionConstTypePtr *p_args, int p_argument_count); + +typedef GDExtensionObjectPtr (*GDExtensionClassConstructor)(); + +typedef void *(*GDExtensionInstanceBindingCreateCallback)(void *p_token, void *p_instance); +typedef void (*GDExtensionInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding); +typedef GDExtensionBool (*GDExtensionInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDExtensionBool p_reference); + +typedef struct { + GDExtensionInstanceBindingCreateCallback create_callback; + GDExtensionInstanceBindingFreeCallback free_callback; + GDExtensionInstanceBindingReferenceCallback reference_callback; +} GDExtensionInstanceBindingCallbacks; + +/* EXTENSION CLASSES */ + +typedef void *GDExtensionClassInstancePtr; + +typedef GDExtensionBool (*GDExtensionClassSet)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value); +typedef GDExtensionBool (*GDExtensionClassGet)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef uint64_t (*GDExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance); + +typedef struct { + GDExtensionVariantType type; + GDExtensionStringNamePtr name; + GDExtensionStringNamePtr class_name; + uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`). + GDExtensionStringPtr hint_string; + uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`). +} GDExtensionPropertyInfo; + +typedef struct { + GDExtensionStringNamePtr name; + GDExtensionPropertyInfo return_value; + uint32_t flags; // Bitfield of `GDExtensionClassMethodFlags`. + int32_t id; + + /* Arguments: `default_arguments` is an array of size `argument_count`. */ + uint32_t argument_count; + GDExtensionPropertyInfo *arguments; + + /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */ + uint32_t default_argument_count; + GDExtensionVariantPtr *default_arguments; +} GDExtensionMethodInfo; + +typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); +typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list); +typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name); +typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); +typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out); +typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance); +typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); +typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); +typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_userdata); +typedef void (*GDExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); +typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_userdata, GDExtensionConstStringNamePtr p_name); + +typedef struct { + GDExtensionBool is_virtual; + GDExtensionBool is_abstract; + GDExtensionClassSet set_func; + GDExtensionClassGet get_func; + GDExtensionClassGetPropertyList get_property_list_func; + GDExtensionClassFreePropertyList free_property_list_func; + GDExtensionClassPropertyCanRevert property_can_revert_func; + GDExtensionClassPropertyGetRevert property_get_revert_func; + GDExtensionClassNotification notification_func; + GDExtensionClassToString to_string_func; + GDExtensionClassReference reference_func; + GDExtensionClassUnreference unreference_func; + GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract. + GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory. + GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function. + GDExtensionClassGetRID get_rid_func; + void *class_userdata; // Per-class user data, later accessible in instance bindings. +} GDExtensionClassCreationInfo; + +typedef void *GDExtensionClassLibraryPtr; + +/* Method */ + +typedef enum { + GDEXTENSION_METHOD_FLAG_NORMAL = 1, + GDEXTENSION_METHOD_FLAG_EDITOR = 2, + GDEXTENSION_METHOD_FLAG_CONST = 4, + GDEXTENSION_METHOD_FLAG_VIRTUAL = 8, + GDEXTENSION_METHOD_FLAG_VARARG = 16, + GDEXTENSION_METHOD_FLAG_STATIC = 32, + GDEXTENSION_METHOD_FLAGS_DEFAULT = GDEXTENSION_METHOD_FLAG_NORMAL, +} GDExtensionClassMethodFlags; + +typedef enum { + GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32, + GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64, + GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT, + GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE +} GDExtensionClassMethodArgumentMetadata; + +typedef void (*GDExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); +typedef void (*GDExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); + +typedef struct { + GDExtensionStringNamePtr name; + void *method_userdata; + GDExtensionClassMethodCall call_func; + GDExtensionClassMethodPtrCall ptrcall_func; + uint32_t method_flags; // Bitfield of `GDExtensionClassMethodFlags`. + + /* If `has_return_value` is false, `return_value_info` and `return_value_metadata` are ignored. */ + GDExtensionBool has_return_value; + GDExtensionPropertyInfo *return_value_info; + GDExtensionClassMethodArgumentMetadata return_value_metadata; + + /* Arguments: `arguments_info` and `arguments_metadata` are array of size `argument_count`. + * Name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. + */ + uint32_t argument_count; + GDExtensionPropertyInfo *arguments_info; + GDExtensionClassMethodArgumentMetadata *arguments_metadata; + + /* Default arguments: `default_arguments` is an array of size `default_argument_count`. */ + uint32_t default_argument_count; + GDExtensionVariantPtr *default_arguments; +} GDExtensionClassMethodInfo; + +/* SCRIPT INSTANCE EXTENSION */ + +typedef void *GDExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation. + +typedef GDExtensionBool (*GDExtensionScriptInstanceSet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value); +typedef GDExtensionBool (*GDExtensionScriptInstanceGet)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef const GDExtensionPropertyInfo *(*GDExtensionScriptInstanceGetPropertyList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); +typedef void (*GDExtensionScriptInstanceFreePropertyList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionPropertyInfo *p_list); +typedef GDExtensionVariantType (*GDExtensionScriptInstanceGetPropertyType)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionBool *r_is_valid); + +typedef GDExtensionBool (*GDExtensionScriptInstancePropertyCanRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name); +typedef GDExtensionBool (*GDExtensionScriptInstancePropertyGetRevert)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); + +typedef GDExtensionObjectPtr (*GDExtensionScriptInstanceGetOwner)(GDExtensionScriptInstanceDataPtr p_instance); +typedef void (*GDExtensionScriptInstancePropertyStateAdd)(GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value, void *p_userdata); +typedef void (*GDExtensionScriptInstanceGetPropertyState)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata); + +typedef const GDExtensionMethodInfo *(*GDExtensionScriptInstanceGetMethodList)(GDExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); +typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanceDataPtr p_instance, const GDExtensionMethodInfo *p_list); + +typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name); + +typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); +typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what); +typedef void (*GDExtensionScriptInstanceToString)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out); + +typedef void (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance); +typedef GDExtensionBool (*GDExtensionScriptInstanceRefCountDecremented)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef GDExtensionObjectPtr (*GDExtensionScriptInstanceGetScript)(GDExtensionScriptInstanceDataPtr p_instance); +typedef GDExtensionBool (*GDExtensionScriptInstanceIsPlaceholder)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef void *GDExtensionScriptLanguagePtr; + +typedef GDExtensionScriptLanguagePtr (*GDExtensionScriptInstanceGetLanguage)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef void (*GDExtensionScriptInstanceFree)(GDExtensionScriptInstanceDataPtr p_instance); + +typedef void *GDExtensionScriptInstancePtr; // Pointer to ScriptInstance. + +typedef struct { + GDExtensionScriptInstanceSet set_func; + GDExtensionScriptInstanceGet get_func; + GDExtensionScriptInstanceGetPropertyList get_property_list_func; + GDExtensionScriptInstanceFreePropertyList free_property_list_func; + + GDExtensionScriptInstancePropertyCanRevert property_can_revert_func; + GDExtensionScriptInstancePropertyGetRevert property_get_revert_func; + + GDExtensionScriptInstanceGetOwner get_owner_func; + GDExtensionScriptInstanceGetPropertyState get_property_state_func; + + GDExtensionScriptInstanceGetMethodList get_method_list_func; + GDExtensionScriptInstanceFreeMethodList free_method_list_func; + GDExtensionScriptInstanceGetPropertyType get_property_type_func; + + GDExtensionScriptInstanceHasMethod has_method_func; + + GDExtensionScriptInstanceCall call_func; + GDExtensionScriptInstanceNotification notification_func; + + GDExtensionScriptInstanceToString to_string_func; + + GDExtensionScriptInstanceRefCountIncremented refcount_incremented_func; + GDExtensionScriptInstanceRefCountDecremented refcount_decremented_func; + + GDExtensionScriptInstanceGetScript get_script_func; + + GDExtensionScriptInstanceIsPlaceholder is_placeholder_func; + + GDExtensionScriptInstanceSet set_fallback_func; + GDExtensionScriptInstanceGet get_fallback_func; + + GDExtensionScriptInstanceGetLanguage get_language_func; + + GDExtensionScriptInstanceFree free_func; + +} GDExtensionScriptInstanceInfo; + +/* INTERFACE */ + +typedef struct { + uint32_t version_major; + uint32_t version_minor; + uint32_t version_patch; + const char *version_string; + + /* GODOT CORE */ + + void *(*mem_alloc)(size_t p_bytes); + void *(*mem_realloc)(void *p_ptr, size_t p_bytes); + void (*mem_free)(void *p_ptr); + + void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_error_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_warning_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + void (*print_script_error_with_message)(const char *p_description, const char *p_message, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify); + + uint64_t (*get_native_struct_size)(GDExtensionConstStringNamePtr p_name); + + /* GODOT VARIANT */ + + /* variant general */ + void (*variant_new_copy)(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src); + void (*variant_new_nil)(GDExtensionVariantPtr r_dest); + void (*variant_destroy)(GDExtensionVariantPtr p_self); + + /* variant type */ + void (*variant_call)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); + void (*variant_call_static)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); + void (*variant_evaluate)(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid); + void (*variant_set)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid); + void (*variant_set_named)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid); + void (*variant_set_keyed)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid); + void (*variant_set_indexed)(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob); + void (*variant_get)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + void (*variant_get_named)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + void (*variant_get_keyed)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + void (*variant_get_indexed)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob); + GDExtensionBool (*variant_iter_init)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid); + GDExtensionBool (*variant_iter_next)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid); + void (*variant_iter_get)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid); + GDExtensionInt (*variant_hash)(GDExtensionConstVariantPtr p_self); + GDExtensionInt (*variant_recursive_hash)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count); + GDExtensionBool (*variant_hash_compare)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other); + GDExtensionBool (*variant_booleanize)(GDExtensionConstVariantPtr p_self); + void (*variant_duplicate)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep); + void (*variant_stringify)(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret); + + GDExtensionVariantType (*variant_get_type)(GDExtensionConstVariantPtr p_self); + GDExtensionBool (*variant_has_method)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method); + GDExtensionBool (*variant_has_member)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member); + GDExtensionBool (*variant_has_key)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid); + void (*variant_get_type_name)(GDExtensionVariantType p_type, GDExtensionStringPtr r_name); + GDExtensionBool (*variant_can_convert)(GDExtensionVariantType p_from, GDExtensionVariantType p_to); + GDExtensionBool (*variant_can_convert_strict)(GDExtensionVariantType p_from, GDExtensionVariantType p_to); + + /* ptrcalls */ + GDExtensionVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDExtensionVariantType p_type); + GDExtensionTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDExtensionVariantType p_type); + GDExtensionPtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDExtensionVariantOperator p_operator, GDExtensionVariantType p_type_a, GDExtensionVariantType p_type_b); + GDExtensionPtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash); + GDExtensionPtrConstructor (*variant_get_ptr_constructor)(GDExtensionVariantType p_type, int32_t p_constructor); + GDExtensionPtrDestructor (*variant_get_ptr_destructor)(GDExtensionVariantType p_type); + void (*variant_construct)(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error); + GDExtensionPtrSetter (*variant_get_ptr_setter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member); + GDExtensionPtrGetter (*variant_get_ptr_getter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member); + GDExtensionPtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDExtensionVariantType p_type); + GDExtensionPtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDExtensionVariantType p_type); + GDExtensionPtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDExtensionVariantType p_type); + GDExtensionPtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDExtensionVariantType p_type); + GDExtensionPtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDExtensionVariantType p_type); + void (*variant_get_constant_value)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret); + GDExtensionPtrUtilityFunction (*variant_get_ptr_utility_function)(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash); + + /* extra utilities */ + void (*string_new_with_latin1_chars)(GDExtensionStringPtr r_dest, const char *p_contents); + void (*string_new_with_utf8_chars)(GDExtensionStringPtr r_dest, const char *p_contents); + void (*string_new_with_utf16_chars)(GDExtensionStringPtr r_dest, const char16_t *p_contents); + void (*string_new_with_utf32_chars)(GDExtensionStringPtr r_dest, const char32_t *p_contents); + void (*string_new_with_wide_chars)(GDExtensionStringPtr r_dest, const wchar_t *p_contents); + void (*string_new_with_latin1_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size); + void (*string_new_with_utf8_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size); + void (*string_new_with_utf16_chars_and_len)(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size); + void (*string_new_with_utf32_chars_and_len)(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size); + void (*string_new_with_wide_chars_and_len)(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size); + /* Information about the following functions: + * - The return value is the resulting encoded string length. + * - The length returned is in characters, not in bytes. It also does not include a trailing zero. + * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it). + * - Passing NULL in r_text means only the length is computed (again, without including trailing zero). + * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL. + * - p_max_write_length argument does not affect the return value, it's only to cap write length. + */ + GDExtensionInt (*string_to_latin1_chars)(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_utf8_chars)(GDExtensionConstStringPtr p_self, char *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_utf16_chars)(GDExtensionConstStringPtr p_self, char16_t *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_utf32_chars)(GDExtensionConstStringPtr p_self, char32_t *r_text, GDExtensionInt p_max_write_length); + GDExtensionInt (*string_to_wide_chars)(GDExtensionConstStringPtr p_self, wchar_t *r_text, GDExtensionInt p_max_write_length); + char32_t *(*string_operator_index)(GDExtensionStringPtr p_self, GDExtensionInt p_index); + const char32_t *(*string_operator_index_const)(GDExtensionConstStringPtr p_self, GDExtensionInt p_index); + + void (*string_operator_plus_eq_string)(GDExtensionStringPtr p_self, GDExtensionConstStringPtr p_b); + void (*string_operator_plus_eq_char)(GDExtensionStringPtr p_self, char32_t p_b); + void (*string_operator_plus_eq_cstr)(GDExtensionStringPtr p_self, const char *p_b); + void (*string_operator_plus_eq_wcstr)(GDExtensionStringPtr p_self, const wchar_t *p_b); + void (*string_operator_plus_eq_c32str)(GDExtensionStringPtr p_self, const char32_t *p_b); + + /* XMLParser extra utilities */ + + GDExtensionInt (*xml_parser_open_buffer)(GDExtensionObjectPtr p_instance, const uint8_t *p_buffer, size_t p_size); + + /* FileAccess extra utilities */ + + void (*file_access_store_buffer)(GDExtensionObjectPtr p_instance, const uint8_t *p_src, uint64_t p_length); + uint64_t (*file_access_get_buffer)(GDExtensionConstObjectPtr p_instance, uint8_t *p_dst, uint64_t p_length); + + /* WorkerThreadPool extra utilities */ + + int64_t (*worker_thread_pool_add_native_group_task)(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description); + int64_t (*worker_thread_pool_add_native_task)(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description); + + /* Packed array functions */ + + uint8_t *(*packed_byte_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray + const uint8_t *(*packed_byte_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedByteArray + + GDExtensionTypePtr (*packed_color_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedColorArray, returns Color ptr + GDExtensionTypePtr (*packed_color_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedColorArray, returns Color ptr + + float *(*packed_float32_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat32Array + const float *(*packed_float32_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat32Array + double *(*packed_float64_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat64Array + const double *(*packed_float64_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedFloat64Array + + int32_t *(*packed_int32_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + const int32_t *(*packed_int32_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + int64_t *(*packed_int64_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + const int64_t *(*packed_int64_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedInt32Array + + GDExtensionStringPtr (*packed_string_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedStringArray + GDExtensionStringPtr (*packed_string_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedStringArray + + GDExtensionTypePtr (*packed_vector2_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr + GDExtensionTypePtr (*packed_vector2_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr + GDExtensionTypePtr (*packed_vector3_array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr + GDExtensionTypePtr (*packed_vector3_array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr + + GDExtensionVariantPtr (*array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr + GDExtensionVariantPtr (*array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr + void (*array_ref)(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from); // p_self should be an Array ptr + void (*array_set_typed)(GDExtensionTypePtr p_self, GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script); // p_self should be an Array ptr + + /* Dictionary functions */ + + GDExtensionVariantPtr (*dictionary_operator_index)(GDExtensionTypePtr p_self, GDExtensionConstVariantPtr p_key); // p_self should be an Dictionary ptr + GDExtensionVariantPtr (*dictionary_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key); // p_self should be an Dictionary ptr + + /* OBJECT */ + + void (*object_method_bind_call)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_ret, GDExtensionCallError *r_error); + void (*object_method_bind_ptrcall)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); + void (*object_destroy)(GDExtensionObjectPtr p_o); + GDExtensionObjectPtr (*global_get_singleton)(GDExtensionConstStringNamePtr p_name); + + void *(*object_get_instance_binding)(GDExtensionObjectPtr p_o, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks); + void (*object_set_instance_binding)(GDExtensionObjectPtr p_o, void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks); + + void (*object_set_instance)(GDExtensionObjectPtr p_o, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ + + GDExtensionObjectPtr (*object_cast_to)(GDExtensionConstObjectPtr p_object, void *p_class_tag); + GDExtensionObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); + GDObjectInstanceID (*object_get_instance_id)(GDExtensionConstObjectPtr p_object); + + /* REFERENCE */ + + GDExtensionObjectPtr (*ref_get_object)(GDExtensionConstRefPtr p_ref); + void (*ref_set_object)(GDExtensionRefPtr p_ref, GDExtensionObjectPtr p_object); + + /* SCRIPT INSTANCE */ + + GDExtensionScriptInstancePtr (*script_instance_create)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data); + + /* CLASSDB */ + + GDExtensionObjectPtr (*classdb_construct_object)(GDExtensionConstStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ + GDExtensionMethodBindPtr (*classdb_get_method_bind)(GDExtensionConstStringNamePtr p_classname, GDExtensionConstStringNamePtr p_methodname, GDExtensionInt p_hash); + void *(*classdb_get_class_tag)(GDExtensionConstStringNamePtr p_classname); + + /* CLASSDB EXTENSION */ + + /* Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns. */ + void (*classdb_register_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs); + void (*classdb_register_extension_class_method)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info); + void (*classdb_register_extension_class_integer_constant)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield); + void (*classdb_register_extension_class_property)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter); + void (*classdb_register_extension_class_property_group)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_group_name, GDExtensionConstStringPtr p_prefix); + void (*classdb_register_extension_class_property_subgroup)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringPtr p_subgroup_name, GDExtensionConstStringPtr p_prefix); + void (*classdb_register_extension_class_signal)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count); + void (*classdb_unregister_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ + + void (*get_library_path)(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path); + +} GDExtensionInterface; + +/* INITIALIZATION */ + +typedef enum { + GDEXTENSION_INITIALIZATION_CORE, + GDEXTENSION_INITIALIZATION_SERVERS, + GDEXTENSION_INITIALIZATION_SCENE, + GDEXTENSION_INITIALIZATION_EDITOR, + GDEXTENSION_MAX_INITIALIZATION_LEVEL, +} GDExtensionInitializationLevel; + +typedef struct { + /* Minimum initialization level required. + * If Core or Servers, the extension needs editor or game restart to take effect */ + GDExtensionInitializationLevel minimum_initialization_level; + /* Up to the user to supply when initializing */ + void *userdata; + /* This function will be called multiple times for each initialization level. */ + void (*initialize)(void *userdata, GDExtensionInitializationLevel p_level); + void (*deinitialize)(void *userdata, GDExtensionInitializationLevel p_level); +} GDExtensionInitialization; + +/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar). + * This is the entry point of the GDExtension library and will be called on initialization. + * It can be used to set up different init levels, which are called during various stages of initialization/shutdown. + * The function name must be a unique one specified in the .gdextension config file. + */ +typedef GDExtensionBool (*GDExtensionInitializationFunction)(const GDExtensionInterface *p_interface, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization); + +#ifdef __cplusplus +} +#endif + +#endif // GDEXTENSION_INTERFACE_H diff --git a/core/extension/gdextension_manager.cpp b/core/extension/gdextension_manager.cpp new file mode 100644 index 0000000000..8701e6d77b --- /dev/null +++ b/core/extension/gdextension_manager.cpp @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* gdextension_manager.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gdextension_manager.h" +#include "core/io/file_access.h" + +GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &p_path) { + if (gdextension_map.has(p_path)) { + return LOAD_STATUS_ALREADY_LOADED; + } + Ref<GDExtension> extension = ResourceLoader::load(p_path); + if (extension.is_null()) { + return LOAD_STATUS_FAILED; + } + + if (level >= 0) { // Already initialized up to some level. + int32_t minimum_level = extension->get_minimum_library_initialization_level(); + if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) { + return LOAD_STATUS_NEEDS_RESTART; + } + // Initialize up to current level. + for (int32_t i = minimum_level; i <= level; i++) { + extension->initialize_library(GDExtension::InitializationLevel(i)); + } + } + gdextension_map[p_path] = extension; + return LOAD_STATUS_OK; +} + +GDExtensionManager::LoadStatus GDExtensionManager::reload_extension(const String &p_path) { + return LOAD_STATUS_OK; //TODO +} +GDExtensionManager::LoadStatus GDExtensionManager::unload_extension(const String &p_path) { + if (!gdextension_map.has(p_path)) { + return LOAD_STATUS_NOT_LOADED; + } + + Ref<GDExtension> extension = gdextension_map[p_path]; + + if (level >= 0) { // Already initialized up to some level. + int32_t minimum_level = extension->get_minimum_library_initialization_level(); + if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) { + return LOAD_STATUS_NEEDS_RESTART; + } + // Deinitialize down to current level. + for (int32_t i = level; i >= minimum_level; i--) { + extension->deinitialize_library(GDExtension::InitializationLevel(i)); + } + } + gdextension_map.erase(p_path); + return LOAD_STATUS_OK; +} + +bool GDExtensionManager::is_extension_loaded(const String &p_path) const { + return gdextension_map.has(p_path); +} + +Vector<String> GDExtensionManager::get_loaded_extensions() const { + Vector<String> ret; + for (const KeyValue<String, Ref<GDExtension>> &E : gdextension_map) { + ret.push_back(E.key); + } + return ret; +} +Ref<GDExtension> GDExtensionManager::get_extension(const String &p_path) { + HashMap<String, Ref<GDExtension>>::Iterator E = gdextension_map.find(p_path); + ERR_FAIL_COND_V(!E, Ref<GDExtension>()); + return E->value; +} + +void GDExtensionManager::initialize_extensions(GDExtension::InitializationLevel p_level) { + ERR_FAIL_COND(int32_t(p_level) - 1 != level); + for (KeyValue<String, Ref<GDExtension>> &E : gdextension_map) { + E.value->initialize_library(p_level); + } + level = p_level; +} + +void GDExtensionManager::deinitialize_extensions(GDExtension::InitializationLevel p_level) { + ERR_FAIL_COND(int32_t(p_level) != level); + for (KeyValue<String, Ref<GDExtension>> &E : gdextension_map) { + E.value->deinitialize_library(p_level); + } + level = int32_t(p_level) - 1; +} + +void GDExtensionManager::load_extensions() { + Ref<FileAccess> f = FileAccess::open(GDExtension::get_extension_list_config_file(), FileAccess::READ); + while (f.is_valid() && !f->eof_reached()) { + String s = f->get_line().strip_edges(); + if (!s.is_empty()) { + LoadStatus err = load_extension(s); + ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s); + } + } +} + +GDExtensionManager *GDExtensionManager::get_singleton() { + return singleton; +} +void GDExtensionManager::_bind_methods() { + ClassDB::bind_method(D_METHOD("load_extension", "path"), &GDExtensionManager::load_extension); + ClassDB::bind_method(D_METHOD("reload_extension", "path"), &GDExtensionManager::reload_extension); + ClassDB::bind_method(D_METHOD("unload_extension", "path"), &GDExtensionManager::unload_extension); + ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &GDExtensionManager::is_extension_loaded); + + ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &GDExtensionManager::get_loaded_extensions); + ClassDB::bind_method(D_METHOD("get_extension", "path"), &GDExtensionManager::get_extension); + + BIND_ENUM_CONSTANT(LOAD_STATUS_OK); + BIND_ENUM_CONSTANT(LOAD_STATUS_FAILED); + BIND_ENUM_CONSTANT(LOAD_STATUS_ALREADY_LOADED); + BIND_ENUM_CONSTANT(LOAD_STATUS_NOT_LOADED); + BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART); +} + +GDExtensionManager *GDExtensionManager::singleton = nullptr; + +GDExtensionManager::GDExtensionManager() { + ERR_FAIL_COND(singleton != nullptr); + singleton = this; +} diff --git a/core/extension/native_extension_manager.h b/core/extension/gdextension_manager.h index ed80cd6b7a..456942af0d 100644 --- a/core/extension/native_extension_manager.h +++ b/core/extension/gdextension_manager.h @@ -1,47 +1,47 @@ -/*************************************************************************/ -/* native_extension_manager.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdextension_manager.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ -#ifndef NATIVE_EXTENSION_MANAGER_H -#define NATIVE_EXTENSION_MANAGER_H +#ifndef GDEXTENSION_MANAGER_H +#define GDEXTENSION_MANAGER_H -#include "core/extension/native_extension.h" +#include "core/extension/gdextension.h" -class NativeExtensionManager : public Object { - GDCLASS(NativeExtensionManager, Object); +class GDExtensionManager : public Object { + GDCLASS(GDExtensionManager, Object); int32_t level = -1; - HashMap<String, Ref<NativeExtension>> native_extension_map; + HashMap<String, Ref<GDExtension>> gdextension_map; static void _bind_methods(); - static NativeExtensionManager *singleton; + static GDExtensionManager *singleton; public: enum LoadStatus { @@ -57,18 +57,18 @@ public: LoadStatus unload_extension(const String &p_path); bool is_extension_loaded(const String &p_path) const; Vector<String> get_loaded_extensions() const; - Ref<NativeExtension> get_extension(const String &p_path); + Ref<GDExtension> get_extension(const String &p_path); - void initialize_extensions(NativeExtension::InitializationLevel p_level); - void deinitialize_extensions(NativeExtension::InitializationLevel p_level); + void initialize_extensions(GDExtension::InitializationLevel p_level); + void deinitialize_extensions(GDExtension::InitializationLevel p_level); - static NativeExtensionManager *get_singleton(); + static GDExtensionManager *get_singleton(); void load_extensions(); - NativeExtensionManager(); + GDExtensionManager(); }; -VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus) +VARIANT_ENUM_CAST(GDExtensionManager::LoadStatus) -#endif // NATIVE_EXTENSION_MANAGER_H +#endif // GDEXTENSION_MANAGER_H diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp deleted file mode 100644 index 193fcb8916..0000000000 --- a/core/extension/gdnative_interface.cpp +++ /dev/null @@ -1,1074 +0,0 @@ -/*************************************************************************/ -/* gdnative_interface.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gdnative_interface.h" - -#include "core/config/engine.h" -#include "core/object/class_db.h" -#include "core/object/script_language_extension.h" -#include "core/os/memory.h" -#include "core/variant/variant.h" -#include "core/version.h" - -// Memory Functions -static void *gdnative_alloc(size_t p_size) { - return memalloc(p_size); -} - -static void *gdnative_realloc(void *p_mem, size_t p_size) { - return memrealloc(p_mem, p_size); -} - -static void gdnative_free(void *p_mem) { - memfree(p_mem); -} - -// Helper print functions. -static void gdnative_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR); -} -static void gdnative_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING); -} -static void gdnative_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); -} - -uint64_t gdnative_get_native_struct_size(const char *p_name) { - return ClassDB::get_native_struct_size(p_name); -} - -// Variant functions - -static void gdnative_variant_new_copy(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src) { - memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<Variant *>(p_src))); -} -static void gdnative_variant_new_nil(GDNativeVariantPtr r_dest) { - memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant); -} -static void gdnative_variant_destroy(GDNativeVariantPtr p_self) { - reinterpret_cast<Variant *>(p_self)->~Variant(); -} - -// variant type - -static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { - Variant *self = (Variant *)p_self; - const StringName *method = (const StringName *)p_method; - const Variant **args = (const Variant **)p_args; - Variant ret; - Callable::CallError error; - self->callp(*method, args, p_argcount, ret, error); - memnew_placement(r_return, Variant(ret)); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)(error.error); - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} - -static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { - Variant::Type type = (Variant::Type)p_type; - const StringName *method = (const StringName *)p_method; - const Variant **args = (const Variant **)p_args; - Variant ret; - Callable::CallError error; - Variant::call_static(type, *method, args, p_argcount, ret, error); - memnew_placement(r_return, Variant(ret)); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)error.error; - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} - -static void gdnative_variant_evaluate(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid) { - Variant::Operator op = (Variant::Operator)p_op; - const Variant *a = (const Variant *)p_a; - const Variant *b = (const Variant *)p_b; - Variant *ret = (Variant *)r_return; - bool valid; - Variant::evaluate(op, *a, *b, *ret, valid); - *r_valid = valid; -} - -static void gdnative_variant_set(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) { - Variant *self = (Variant *)p_self; - const Variant *key = (const Variant *)p_key; - const Variant *value = (const Variant *)p_value; - - bool valid; - self->set(*key, *value, &valid); - *r_valid = valid; -} - -static void gdnative_variant_set_named(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) { - Variant *self = (Variant *)p_self; - const StringName *key = (const StringName *)p_key; - const Variant *value = (const Variant *)p_value; - - bool valid; - self->set_named(*key, *value, valid); - *r_valid = valid; -} - -static void gdnative_variant_set_keyed(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid) { - Variant *self = (Variant *)p_self; - const Variant *key = (const Variant *)p_key; - const Variant *value = (const Variant *)p_value; - - bool valid; - self->set_keyed(*key, *value, valid); - *r_valid = valid; -} - -static void gdnative_variant_set_indexed(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob) { - Variant *self = (Variant *)p_self; - const Variant *value = (const Variant *)p_value; - - bool valid; - bool oob; - self->set_indexed(p_index, *value, valid, oob); - *r_valid = valid; - *r_oob = oob; -} - -static void gdnative_variant_get(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const Variant *key = (const Variant *)p_key; - - bool valid; - memnew_placement(r_ret, Variant(self->get(*key, &valid))); - *r_valid = valid; -} - -static void gdnative_variant_get_named(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const StringName *key = (const StringName *)p_key; - - bool valid; - memnew_placement(r_ret, Variant(self->get_named(*key, valid))); - *r_valid = valid; -} - -static void gdnative_variant_get_keyed(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const Variant *key = (const Variant *)p_key; - - bool valid; - memnew_placement(r_ret, Variant(self->get_keyed(*key, valid))); - *r_valid = valid; -} - -static void gdnative_variant_get_indexed(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob) { - const Variant *self = (const Variant *)p_self; - - bool valid; - bool oob; - memnew_placement(r_ret, Variant(self->get_indexed(p_index, valid, oob))); - *r_valid = valid; - *r_oob = oob; -} - -/// Iteration. -static GDNativeBool gdnative_variant_iter_init(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - Variant *iter = (Variant *)r_iter; - - bool valid; - bool ret = self->iter_init(*iter, valid); - *r_valid = valid; - return ret; -} - -static GDNativeBool gdnative_variant_iter_next(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - Variant *iter = (Variant *)r_iter; - - bool valid; - bool ret = self->iter_next(*iter, valid); - *r_valid = valid; - return ret; -} - -static void gdnative_variant_iter_get(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - Variant *iter = (Variant *)r_iter; - - bool valid; - memnew_placement(r_ret, Variant(self->iter_next(*iter, valid))); - *r_valid = valid; -} - -/// Variant functions. -static GDNativeInt gdnative_variant_hash(const GDNativeVariantPtr p_self) { - const Variant *self = (const Variant *)p_self; - return self->hash(); -} - -static GDNativeInt gdnative_variant_recursive_hash(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count) { - const Variant *self = (const Variant *)p_self; - return self->recursive_hash(p_recursion_count); -} - -static GDNativeBool gdnative_variant_hash_compare(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other) { - const Variant *self = (const Variant *)p_self; - const Variant *other = (const Variant *)p_other; - return self->hash_compare(*other); -} - -static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self) { - const Variant *self = (const Variant *)p_self; - return self->booleanize(); -} - -static void gdnative_variant_duplicate(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep) { - const Variant *self = (const Variant *)p_self; - memnew_placement(r_ret, Variant(self->duplicate(p_deep))); -} - -static void gdnative_variant_stringify(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret) { - const Variant *self = (const Variant *)p_self; - memnew_placement(r_ret, String(*self)); -} - -static GDNativeVariantType gdnative_variant_get_type(const GDNativeVariantPtr p_self) { - const Variant *self = (const Variant *)p_self; - return (GDNativeVariantType)self->get_type(); -} - -static GDNativeBool gdnative_variant_has_method(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method) { - const Variant *self = (const Variant *)p_self; - const StringName *method = (const StringName *)p_method; - return self->has_method(*method); -} - -static GDNativeBool gdnative_variant_has_member(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) { - return Variant::has_member((Variant::Type)p_type, *((const StringName *)p_member)); -} - -static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid) { - const Variant *self = (const Variant *)p_self; - const Variant *key = (const Variant *)p_key; - bool valid; - bool ret = self->has_key(*key, valid); - *r_valid = valid; - return ret; -} - -static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) { - String name = Variant::get_type_name((Variant::Type)p_type); - memnew_placement(r_ret, String(name)); -} - -static GDNativeBool gdnative_variant_can_convert(GDNativeVariantType p_from, GDNativeVariantType p_to) { - return Variant::can_convert((Variant::Type)p_from, (Variant::Type)p_to); -} - -static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_from, GDNativeVariantType p_to) { - return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to); -} - -// Variant interaction. -static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_constructor(GDNativeVariantType p_type) { - switch (p_type) { - case GDNATIVE_VARIANT_TYPE_BOOL: - return VariantTypeConstructor<bool>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_INT: - return VariantTypeConstructor<int64_t>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_FLOAT: - return VariantTypeConstructor<double>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_STRING: - return VariantTypeConstructor<String>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR2: - return VariantTypeConstructor<Vector2>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR2I: - return VariantTypeConstructor<Vector2i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_RECT2: - return VariantTypeConstructor<Rect2>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_RECT2I: - return VariantTypeConstructor<Rect2i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR3: - return VariantTypeConstructor<Vector3>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR3I: - return VariantTypeConstructor<Vector3i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: - return VariantTypeConstructor<Transform2D>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR4: - return VariantTypeConstructor<Vector4>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_VECTOR4I: - return VariantTypeConstructor<Vector4i>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PLANE: - return VariantTypeConstructor<Plane>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_QUATERNION: - return VariantTypeConstructor<Quaternion>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_AABB: - return VariantTypeConstructor<AABB>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_BASIS: - return VariantTypeConstructor<Basis>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: - return VariantTypeConstructor<Transform3D>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PROJECTION: - return VariantTypeConstructor<Projection>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_COLOR: - return VariantTypeConstructor<Color>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_STRING_NAME: - return VariantTypeConstructor<StringName>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_NODE_PATH: - return VariantTypeConstructor<NodePath>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_RID: - return VariantTypeConstructor<RID>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_OBJECT: - return VariantTypeConstructor<Object *>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_CALLABLE: - return VariantTypeConstructor<Callable>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_SIGNAL: - return VariantTypeConstructor<Signal>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_DICTIONARY: - return VariantTypeConstructor<Dictionary>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_ARRAY: - return VariantTypeConstructor<Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY: - return VariantTypeConstructor<PackedByteArray>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY: - return VariantTypeConstructor<PackedInt32Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY: - return VariantTypeConstructor<PackedInt64Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: - return VariantTypeConstructor<PackedFloat32Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: - return VariantTypeConstructor<PackedFloat64Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY: - return VariantTypeConstructor<PackedStringArray>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: - return VariantTypeConstructor<PackedVector2Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: - return VariantTypeConstructor<PackedVector3Array>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY: - return VariantTypeConstructor<PackedColorArray>::variant_from_type; - case GDNATIVE_VARIANT_TYPE_NIL: - case GDNATIVE_VARIANT_TYPE_VARIANT_MAX: - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); - } - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); -} - -static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_constructor(GDNativeVariantType p_type) { - switch (p_type) { - case GDNATIVE_VARIANT_TYPE_BOOL: - return VariantTypeConstructor<bool>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_INT: - return VariantTypeConstructor<int64_t>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_FLOAT: - return VariantTypeConstructor<double>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_STRING: - return VariantTypeConstructor<String>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR2: - return VariantTypeConstructor<Vector2>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR2I: - return VariantTypeConstructor<Vector2i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_RECT2: - return VariantTypeConstructor<Rect2>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_RECT2I: - return VariantTypeConstructor<Rect2i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR3: - return VariantTypeConstructor<Vector3>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR3I: - return VariantTypeConstructor<Vector3i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_TRANSFORM2D: - return VariantTypeConstructor<Transform2D>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR4: - return VariantTypeConstructor<Vector4>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_VECTOR4I: - return VariantTypeConstructor<Vector4i>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PLANE: - return VariantTypeConstructor<Plane>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_QUATERNION: - return VariantTypeConstructor<Quaternion>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_AABB: - return VariantTypeConstructor<AABB>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_BASIS: - return VariantTypeConstructor<Basis>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_TRANSFORM3D: - return VariantTypeConstructor<Transform3D>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PROJECTION: - return VariantTypeConstructor<Projection>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_COLOR: - return VariantTypeConstructor<Color>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_STRING_NAME: - return VariantTypeConstructor<StringName>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_NODE_PATH: - return VariantTypeConstructor<NodePath>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_RID: - return VariantTypeConstructor<RID>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_OBJECT: - return VariantTypeConstructor<Object *>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_CALLABLE: - return VariantTypeConstructor<Callable>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_SIGNAL: - return VariantTypeConstructor<Signal>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_DICTIONARY: - return VariantTypeConstructor<Dictionary>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_ARRAY: - return VariantTypeConstructor<Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY: - return VariantTypeConstructor<PackedByteArray>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY: - return VariantTypeConstructor<PackedInt32Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY: - return VariantTypeConstructor<PackedInt64Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY: - return VariantTypeConstructor<PackedFloat32Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY: - return VariantTypeConstructor<PackedFloat64Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY: - return VariantTypeConstructor<PackedStringArray>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY: - return VariantTypeConstructor<PackedVector2Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY: - return VariantTypeConstructor<PackedVector3Array>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY: - return VariantTypeConstructor<PackedColorArray>::type_from_variant; - case GDNATIVE_VARIANT_TYPE_NIL: - case GDNATIVE_VARIANT_TYPE_VARIANT_MAX: - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); - } - ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type"); -} - -// ptrcalls -static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) { - return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b)); -} -static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash) { - StringName method = p_method; - uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method); - if (hash != p_hash) { - ERR_PRINT_ONCE("Error getting method " + String(method) + ", hash mismatch."); - return nullptr; - } - - return (GDNativePtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method); -} -static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) { - return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor); -} -static GDNativePtrDestructor gdnative_variant_get_ptr_destructor(GDNativeVariantType p_type) { - return (GDNativePtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type)); -} -static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) { - memnew_placement(p_base, Variant); - - Callable::CallError error; - Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)(error.error); - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} -static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const char *p_member) { - return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), p_member); -} -static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const char *p_member) { - return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), p_member); -} -static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) { - return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type)); -} -static GDNativePtrIndexedGetter gdnative_variant_get_ptr_indexed_getter(GDNativeVariantType p_type) { - return (GDNativePtrIndexedGetter)Variant::get_member_ptr_indexed_getter(Variant::Type(p_type)); -} -static GDNativePtrKeyedSetter gdnative_variant_get_ptr_keyed_setter(GDNativeVariantType p_type) { - return (GDNativePtrKeyedSetter)Variant::get_member_ptr_keyed_setter(Variant::Type(p_type)); -} -static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVariantType p_type) { - return (GDNativePtrKeyedGetter)Variant::get_member_ptr_keyed_getter(Variant::Type(p_type)); -} -static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) { - return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type)); -} -static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret) { - memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant))); -} -static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const char *p_function, GDNativeInt p_hash) { - StringName function = p_function; - uint32_t hash = Variant::get_utility_function_hash(function); - if (hash != p_hash) { - ERR_PRINT_ONCE("Error getting utility function " + String(function) + ", hash mismatch."); - return nullptr; - } - return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function); -} - -//string helpers - -static void gdnative_string_new_with_latin1_chars(GDNativeStringPtr r_dest, const char *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String(p_contents); -} - -static void gdnative_string_new_with_utf8_chars(GDNativeStringPtr r_dest, const char *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf8(p_contents); -} - -static void gdnative_string_new_with_utf16_chars(GDNativeStringPtr r_dest, const char16_t *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf16(p_contents); -} - -static void gdnative_string_new_with_utf32_chars(GDNativeStringPtr r_dest, const char32_t *p_contents) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents); -} - -static void gdnative_string_new_with_wide_chars(GDNativeStringPtr r_dest, const wchar_t *p_contents) { - String *dest = (String *)r_dest; - if constexpr (sizeof(wchar_t) == 2) { - // wchar_t is 16 bit, parse. - memnew_placement(dest, String); - dest->parse_utf16((const char16_t *)p_contents); - } else { - // wchar_t is 32 bit, copy. - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents); - } -} - -static void gdnative_string_new_with_latin1_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String(p_contents, p_size); -} - -static void gdnative_string_new_with_utf8_chars_and_len(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf8(p_contents, p_size); -} - -static void gdnative_string_new_with_utf16_chars_and_len(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - dest->parse_utf16(p_contents, p_size); -} - -static void gdnative_string_new_with_utf32_chars_and_len(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents, p_size); -} - -static void gdnative_string_new_with_wide_chars_and_len(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size) { - String *dest = (String *)r_dest; - if constexpr (sizeof(wchar_t) == 2) { - // wchar_t is 16 bit, parse. - memnew_placement(dest, String); - dest->parse_utf16((const char16_t *)p_contents, p_size); - } else { - // wchar_t is 32 bit, copy. - memnew_placement(dest, String); - *dest = String((const char32_t *)p_contents, p_size); - } -} - -static GDNativeInt gdnative_string_to_latin1_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - CharString cs = self->ascii(true); - GDNativeInt len = cs.length(); - if (r_text) { - const char *s_text = cs.ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_utf8_chars(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - CharString cs = self->utf8(); - GDNativeInt len = cs.length(); - if (r_text) { - const char *s_text = cs.ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_utf16_chars(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - Char16String cs = self->utf16(); - GDNativeInt len = cs.length(); - if (r_text) { - const char16_t *s_text = cs.ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_utf32_chars(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length) { - String *self = (String *)p_self; - GDNativeInt len = self->length(); - if (r_text) { - const char32_t *s_text = self->ptr(); - for (GDNativeInt i = 0; i < MIN(len, p_max_write_length); i++) { - r_text[i] = s_text[i]; - } - } - return len; -} -static GDNativeInt gdnative_string_to_wide_chars(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length) { - if constexpr (sizeof(wchar_t) == 4) { - return gdnative_string_to_utf32_chars(p_self, (char32_t *)r_text, p_max_write_length); - } else { - return gdnative_string_to_utf16_chars(p_self, (char16_t *)r_text, p_max_write_length); - } -} - -static char32_t *gdnative_string_operator_index(GDNativeStringPtr p_self, GDNativeInt p_index) { - String *self = (String *)p_self; - ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); - return &self->ptrw()[p_index]; -} - -static const char32_t *gdnative_string_operator_index_const(const GDNativeStringPtr p_self, GDNativeInt p_index) { - const String *self = (const String *)p_self; - ERR_FAIL_INDEX_V(p_index, self->length() + 1, nullptr); - return &self->ptr()[p_index]; -} - -/* Packed array functions */ - -static uint8_t *gdnative_packed_byte_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedByteArray *self = (PackedByteArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const uint8_t *gdnative_packed_byte_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedByteArray *self = (const PackedByteArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_color_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedColorArray *self = (PackedColorArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptrw()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_color_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedColorArray *self = (const PackedColorArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptr()[p_index]; -} - -static float *gdnative_packed_float32_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedFloat32Array *self = (PackedFloat32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const float *gdnative_packed_float32_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedFloat32Array *self = (const PackedFloat32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static double *gdnative_packed_float64_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedFloat64Array *self = (PackedFloat64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const double *gdnative_packed_float64_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedFloat64Array *self = (const PackedFloat64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static int32_t *gdnative_packed_int32_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedInt32Array *self = (PackedInt32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const int32_t *gdnative_packed_int32_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedInt32Array *self = (const PackedInt32Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static int64_t *gdnative_packed_int64_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedInt64Array *self = (PackedInt64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptrw()[p_index]; -} - -static const int64_t *gdnative_packed_int64_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedInt64Array *self = (const PackedInt64Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return &self->ptr()[p_index]; -} - -static GDNativeStringPtr gdnative_packed_string_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedStringArray *self = (PackedStringArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeStringPtr)&self->ptrw()[p_index]; -} - -static GDNativeStringPtr gdnative_packed_string_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedStringArray *self = (const PackedStringArray *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeStringPtr)&self->ptr()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector2_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedVector2Array *self = (PackedVector2Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptrw()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector2_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedVector2Array *self = (const PackedVector2Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptr()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector3_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - PackedVector3Array *self = (PackedVector3Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptrw()[p_index]; -} - -static GDNativeTypePtr gdnative_packed_vector3_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const PackedVector3Array *self = (const PackedVector3Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeTypePtr)&self->ptr()[p_index]; -} - -static GDNativeVariantPtr gdnative_array_operator_index(GDNativeTypePtr p_self, GDNativeInt p_index) { - Array *self = (Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeVariantPtr)&self->operator[](p_index); -} - -static GDNativeVariantPtr gdnative_array_operator_index_const(const GDNativeTypePtr p_self, GDNativeInt p_index) { - const Array *self = (const Array *)p_self; - ERR_FAIL_INDEX_V(p_index, self->size(), nullptr); - return (GDNativeVariantPtr)&self->operator[](p_index); -} - -/* Dictionary functions */ - -static GDNativeVariantPtr gdnative_dictionary_operator_index(GDNativeTypePtr p_self, const GDNativeVariantPtr p_key) { - Dictionary *self = (Dictionary *)p_self; - return (GDNativeVariantPtr)&self->operator[](*(const Variant *)p_key); -} - -static GDNativeVariantPtr gdnative_dictionary_operator_index_const(const GDNativeTypePtr p_self, const GDNativeVariantPtr p_key) { - const Dictionary *self = (const Dictionary *)p_self; - return (GDNativeVariantPtr)&self->operator[](*(const Variant *)p_key); -} - -/* OBJECT API */ - -static void gdnative_object_method_bind_call(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error) { - MethodBind *mb = (MethodBind *)p_method_bind; - Object *o = (Object *)p_instance; - const Variant **args = (const Variant **)p_args; - Callable::CallError error; - - Variant ret = mb->call(o, args, p_arg_count, error); - memnew_placement(r_return, Variant(ret)); - - if (r_error) { - r_error->error = (GDNativeCallErrorType)(error.error); - r_error->argument = error.argument; - r_error->expected = error.expected; - } -} - -static void gdnative_object_method_bind_ptrcall(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr p_ret) { - MethodBind *mb = (MethodBind *)p_method_bind; - Object *o = (Object *)p_instance; - mb->ptrcall(o, (const void **)p_args, p_ret); -} - -static void gdnative_object_destroy(GDNativeObjectPtr p_o) { - memdelete((Object *)p_o); -} - -static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) { - return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name)); -} - -static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_object, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) { - Object *o = (Object *)p_object; - return o->get_instance_binding(p_token, p_callbacks); -} - -static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_object, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) { - Object *o = (Object *)p_object; - o->set_instance_binding(p_token, p_binding, p_callbacks); -} - -static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const char *p_classname, GDExtensionClassInstancePtr p_instance) { - Object *o = (Object *)p_object; - ClassDB::set_object_extension_instance(o, p_classname, p_instance); -} - -static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) { - return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id)); -} - -static GDNativeObjectPtr gdnative_object_cast_to(const GDNativeObjectPtr p_object, void *p_class_tag) { - if (!p_object) { - return nullptr; - } - Object *o = (Object *)p_object; - - return o->is_class_ptr(p_class_tag) ? (GDNativeObjectPtr)o : (GDNativeObjectPtr) nullptr; -} - -static GDObjectInstanceID gdnative_object_get_instance_id(const GDNativeObjectPtr p_object) { - const Object *o = (const Object *)p_object; - return (GDObjectInstanceID)o->get_instance_id(); -} - -static GDNativeScriptInstancePtr gdnative_script_instance_create(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data) { - ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension); - script_instance_extension->instance = p_instance_data; - script_instance_extension->native_info = p_info; - return reinterpret_cast<GDNativeScriptInstancePtr>(script_instance_extension); -} - -static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_classname, const char *p_methodname, GDNativeInt p_hash) { - MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname)); - ERR_FAIL_COND_V(!mb, nullptr); - if (mb->get_hash() != p_hash) { - ERR_PRINT("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'."); - return nullptr; - } - // MethodBind *mb = ClassDB::get_method("Node", "get_name"); - return (GDNativeMethodBindPtr)mb; -} - -static GDNativeObjectPtr gdnative_classdb_construct_object(const char *p_classname) { - return (GDNativeObjectPtr)ClassDB::instantiate(p_classname); -} - -static void *gdnative_classdb_get_class_tag(const char *p_classname) { - ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(p_classname); - return class_info ? class_info->class_ptr : nullptr; -} - -void gdnative_setup_interface(GDNativeInterface *p_interface) { - GDNativeInterface &gdni = *p_interface; - - gdni.version_major = VERSION_MAJOR; - gdni.version_minor = VERSION_MINOR; -#if VERSION_PATCH - gdni.version_patch = VERSION_PATCH; -#else - gdni.version_patch = 0; -#endif - gdni.version_string = VERSION_FULL_NAME; - - /* GODOT CORE */ - - gdni.mem_alloc = gdnative_alloc; - gdni.mem_realloc = gdnative_realloc; - gdni.mem_free = gdnative_free; - - gdni.print_error = gdnative_print_error; - gdni.print_warning = gdnative_print_warning; - gdni.print_script_error = gdnative_print_script_error; - - gdni.get_native_struct_size = gdnative_get_native_struct_size; - - /* GODOT VARIANT */ - - // variant general - gdni.variant_new_copy = gdnative_variant_new_copy; - gdni.variant_new_nil = gdnative_variant_new_nil; - gdni.variant_destroy = gdnative_variant_destroy; - - gdni.variant_call = gdnative_variant_call; - gdni.variant_call_static = gdnative_variant_call_static; - gdni.variant_evaluate = gdnative_variant_evaluate; - gdni.variant_set = gdnative_variant_set; - gdni.variant_set_named = gdnative_variant_set_named; - gdni.variant_set_keyed = gdnative_variant_set_keyed; - gdni.variant_set_indexed = gdnative_variant_set_indexed; - gdni.variant_get = gdnative_variant_get; - gdni.variant_get_named = gdnative_variant_get_named; - gdni.variant_get_keyed = gdnative_variant_get_keyed; - gdni.variant_get_indexed = gdnative_variant_get_indexed; - gdni.variant_iter_init = gdnative_variant_iter_init; - gdni.variant_iter_next = gdnative_variant_iter_next; - gdni.variant_iter_get = gdnative_variant_iter_get; - gdni.variant_hash = gdnative_variant_hash; - gdni.variant_recursive_hash = gdnative_variant_recursive_hash; - gdni.variant_hash_compare = gdnative_variant_hash_compare; - gdni.variant_booleanize = gdnative_variant_booleanize; - gdni.variant_duplicate = gdnative_variant_duplicate; - gdni.variant_stringify = gdnative_variant_stringify; - - gdni.variant_get_type = gdnative_variant_get_type; - gdni.variant_has_method = gdnative_variant_has_method; - gdni.variant_has_member = gdnative_variant_has_member; - gdni.variant_has_key = gdnative_variant_has_key; - gdni.variant_get_type_name = gdnative_variant_get_type_name; - gdni.variant_can_convert = gdnative_variant_can_convert; - gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict; - - gdni.get_variant_from_type_constructor = gdnative_get_variant_from_type_constructor; - gdni.get_variant_to_type_constructor = gdnative_get_type_from_variant_constructor; - - // ptrcalls. - - gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator; - gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method; - gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor; - gdni.variant_get_ptr_destructor = gdnative_variant_get_ptr_destructor; - gdni.variant_construct = gdnative_variant_construct; - gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter; - gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter; - gdni.variant_get_ptr_indexed_setter = gdnative_variant_get_ptr_indexed_setter; - gdni.variant_get_ptr_indexed_getter = gdnative_variant_get_ptr_indexed_getter; - gdni.variant_get_ptr_keyed_setter = gdnative_variant_get_ptr_keyed_setter; - gdni.variant_get_ptr_keyed_getter = gdnative_variant_get_ptr_keyed_getter; - gdni.variant_get_ptr_keyed_checker = gdnative_variant_get_ptr_keyed_checker; - gdni.variant_get_constant_value = gdnative_variant_get_constant_value; - gdni.variant_get_ptr_utility_function = gdnative_variant_get_ptr_utility_function; - - // extra utilities - - gdni.string_new_with_latin1_chars = gdnative_string_new_with_latin1_chars; - gdni.string_new_with_utf8_chars = gdnative_string_new_with_utf8_chars; - gdni.string_new_with_utf16_chars = gdnative_string_new_with_utf16_chars; - gdni.string_new_with_utf32_chars = gdnative_string_new_with_utf32_chars; - gdni.string_new_with_wide_chars = gdnative_string_new_with_wide_chars; - gdni.string_new_with_latin1_chars_and_len = gdnative_string_new_with_latin1_chars_and_len; - gdni.string_new_with_utf8_chars_and_len = gdnative_string_new_with_utf8_chars_and_len; - gdni.string_new_with_utf16_chars_and_len = gdnative_string_new_with_utf16_chars_and_len; - gdni.string_new_with_utf32_chars_and_len = gdnative_string_new_with_utf32_chars_and_len; - gdni.string_new_with_wide_chars_and_len = gdnative_string_new_with_wide_chars_and_len; - gdni.string_to_latin1_chars = gdnative_string_to_latin1_chars; - gdni.string_to_utf8_chars = gdnative_string_to_utf8_chars; - gdni.string_to_utf16_chars = gdnative_string_to_utf16_chars; - gdni.string_to_utf32_chars = gdnative_string_to_utf32_chars; - gdni.string_to_wide_chars = gdnative_string_to_wide_chars; - gdni.string_operator_index = gdnative_string_operator_index; - gdni.string_operator_index_const = gdnative_string_operator_index_const; - - /* Packed array functions */ - - gdni.packed_byte_array_operator_index = gdnative_packed_byte_array_operator_index; - gdni.packed_byte_array_operator_index_const = gdnative_packed_byte_array_operator_index_const; - - gdni.packed_color_array_operator_index = gdnative_packed_color_array_operator_index; - gdni.packed_color_array_operator_index_const = gdnative_packed_color_array_operator_index_const; - - gdni.packed_float32_array_operator_index = gdnative_packed_float32_array_operator_index; - gdni.packed_float32_array_operator_index_const = gdnative_packed_float32_array_operator_index_const; - gdni.packed_float64_array_operator_index = gdnative_packed_float64_array_operator_index; - gdni.packed_float64_array_operator_index_const = gdnative_packed_float64_array_operator_index_const; - - gdni.packed_int32_array_operator_index = gdnative_packed_int32_array_operator_index; - gdni.packed_int32_array_operator_index_const = gdnative_packed_int32_array_operator_index_const; - gdni.packed_int64_array_operator_index = gdnative_packed_int64_array_operator_index; - gdni.packed_int64_array_operator_index_const = gdnative_packed_int64_array_operator_index_const; - - gdni.packed_string_array_operator_index = gdnative_packed_string_array_operator_index; - gdni.packed_string_array_operator_index_const = gdnative_packed_string_array_operator_index_const; - - gdni.packed_vector2_array_operator_index = gdnative_packed_vector2_array_operator_index; - gdni.packed_vector2_array_operator_index_const = gdnative_packed_vector2_array_operator_index_const; - gdni.packed_vector3_array_operator_index = gdnative_packed_vector3_array_operator_index; - gdni.packed_vector3_array_operator_index_const = gdnative_packed_vector3_array_operator_index_const; - - gdni.array_operator_index = gdnative_array_operator_index; - gdni.array_operator_index_const = gdnative_array_operator_index_const; - - /* Dictionary functions */ - - gdni.dictionary_operator_index = gdnative_dictionary_operator_index; - gdni.dictionary_operator_index_const = gdnative_dictionary_operator_index_const; - - /* OBJECT */ - - gdni.object_method_bind_call = gdnative_object_method_bind_call; - gdni.object_method_bind_ptrcall = gdnative_object_method_bind_ptrcall; - gdni.object_destroy = gdnative_object_destroy; - gdni.global_get_singleton = gdnative_global_get_singleton; - gdni.object_get_instance_binding = gdnative_object_get_instance_binding; - gdni.object_set_instance_binding = gdnative_object_set_instance_binding; - gdni.object_set_instance = gdnative_object_set_instance; - - gdni.object_cast_to = gdnative_object_cast_to; - gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id; - gdni.object_get_instance_id = gdnative_object_get_instance_id; - - /* SCRIPT INSTANCE */ - - gdni.script_instance_create = gdnative_script_instance_create; - - /* CLASSDB */ - - gdni.classdb_construct_object = gdnative_classdb_construct_object; - gdni.classdb_get_method_bind = gdnative_classdb_get_method_bind; - gdni.classdb_get_class_tag = gdnative_classdb_get_class_tag; - - /* CLASSDB EXTENSION */ - - //these are filled by implementation, since it will want to keep track of registered classes - gdni.classdb_register_extension_class = nullptr; - gdni.classdb_register_extension_class_method = nullptr; - gdni.classdb_register_extension_class_integer_constant = nullptr; - gdni.classdb_register_extension_class_property = nullptr; - gdni.classdb_register_extension_class_property_group = nullptr; - gdni.classdb_register_extension_class_property_subgroup = nullptr; - gdni.classdb_register_extension_class_signal = nullptr; - gdni.classdb_unregister_extension_class = nullptr; - - gdni.get_library_path = nullptr; -} diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h deleted file mode 100644 index 1ce50bc186..0000000000 --- a/core/extension/gdnative_interface.h +++ /dev/null @@ -1,593 +0,0 @@ -/*************************************************************************/ -/* gdnative_interface.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef GDNATIVE_INTERFACE_H -#define GDNATIVE_INTERFACE_H - -/* This is a C class header, you can copy it and use it directly in your own binders. - * Together with the JSON file, you should be able to generate any binder. - */ - -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> - -#ifndef __cplusplus -typedef uint32_t char32_t; -typedef uint16_t char16_t; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* VARIANT TYPES */ - -typedef enum { - GDNATIVE_VARIANT_TYPE_NIL, - - /* atomic types */ - GDNATIVE_VARIANT_TYPE_BOOL, - GDNATIVE_VARIANT_TYPE_INT, - GDNATIVE_VARIANT_TYPE_FLOAT, - GDNATIVE_VARIANT_TYPE_STRING, - - /* math types */ - GDNATIVE_VARIANT_TYPE_VECTOR2, - GDNATIVE_VARIANT_TYPE_VECTOR2I, - GDNATIVE_VARIANT_TYPE_RECT2, - GDNATIVE_VARIANT_TYPE_RECT2I, - GDNATIVE_VARIANT_TYPE_VECTOR3, - GDNATIVE_VARIANT_TYPE_VECTOR3I, - GDNATIVE_VARIANT_TYPE_TRANSFORM2D, - GDNATIVE_VARIANT_TYPE_VECTOR4, - GDNATIVE_VARIANT_TYPE_VECTOR4I, - GDNATIVE_VARIANT_TYPE_PLANE, - GDNATIVE_VARIANT_TYPE_QUATERNION, - GDNATIVE_VARIANT_TYPE_AABB, - GDNATIVE_VARIANT_TYPE_BASIS, - GDNATIVE_VARIANT_TYPE_TRANSFORM3D, - GDNATIVE_VARIANT_TYPE_PROJECTION, - - /* misc types */ - GDNATIVE_VARIANT_TYPE_COLOR, - GDNATIVE_VARIANT_TYPE_STRING_NAME, - GDNATIVE_VARIANT_TYPE_NODE_PATH, - GDNATIVE_VARIANT_TYPE_RID, - GDNATIVE_VARIANT_TYPE_OBJECT, - GDNATIVE_VARIANT_TYPE_CALLABLE, - GDNATIVE_VARIANT_TYPE_SIGNAL, - GDNATIVE_VARIANT_TYPE_DICTIONARY, - GDNATIVE_VARIANT_TYPE_ARRAY, - - /* typed arrays */ - GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY, - GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY, - - GDNATIVE_VARIANT_TYPE_VARIANT_MAX -} GDNativeVariantType; - -typedef enum { - /* comparison */ - GDNATIVE_VARIANT_OP_EQUAL, - GDNATIVE_VARIANT_OP_NOT_EQUAL, - GDNATIVE_VARIANT_OP_LESS, - GDNATIVE_VARIANT_OP_LESS_EQUAL, - GDNATIVE_VARIANT_OP_GREATER, - GDNATIVE_VARIANT_OP_GREATER_EQUAL, - /* mathematic */ - GDNATIVE_VARIANT_OP_ADD, - GDNATIVE_VARIANT_OP_SUBTRACT, - GDNATIVE_VARIANT_OP_MULTIPLY, - GDNATIVE_VARIANT_OP_DIVIDE, - GDNATIVE_VARIANT_OP_NEGATE, - GDNATIVE_VARIANT_OP_POSITIVE, - GDNATIVE_VARIANT_OP_MODULE, - GDNATIVE_VARIANT_OP_POWER, - /* bitwise */ - GDNATIVE_VARIANT_OP_SHIFT_LEFT, - GDNATIVE_VARIANT_OP_SHIFT_RIGHT, - GDNATIVE_VARIANT_OP_BIT_AND, - GDNATIVE_VARIANT_OP_BIT_OR, - GDNATIVE_VARIANT_OP_BIT_XOR, - GDNATIVE_VARIANT_OP_BIT_NEGATE, - /* logic */ - GDNATIVE_VARIANT_OP_AND, - GDNATIVE_VARIANT_OP_OR, - GDNATIVE_VARIANT_OP_XOR, - GDNATIVE_VARIANT_OP_NOT, - /* containment */ - GDNATIVE_VARIANT_OP_IN, - GDNATIVE_VARIANT_OP_MAX - -} GDNativeVariantOperator; - -typedef void *GDNativeVariantPtr; -typedef void *GDNativeStringNamePtr; -typedef void *GDNativeStringPtr; -typedef void *GDNativeObjectPtr; -typedef void *GDNativeTypePtr; -typedef void *GDNativeExtensionPtr; -typedef void *GDNativeMethodBindPtr; -typedef int64_t GDNativeInt; -typedef uint8_t GDNativeBool; -typedef uint64_t GDObjectInstanceID; - -/* VARIANT DATA I/O */ - -typedef enum { - GDNATIVE_CALL_OK, - GDNATIVE_CALL_ERROR_INVALID_METHOD, - GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */ - GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */ - GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */ - GDNATIVE_CALL_ERROR_INSTANCE_IS_NULL, - GDNATIVE_CALL_ERROR_METHOD_NOT_CONST, /* used for const call */ -} GDNativeCallErrorType; - -typedef struct { - GDNativeCallErrorType error; - int32_t argument; - int32_t expected; -} GDNativeCallError; - -typedef void (*GDNativeVariantFromTypeConstructorFunc)(GDNativeVariantPtr, GDNativeTypePtr); -typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNativeVariantPtr); -typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result); -typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count); -typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args); -typedef void (*GDNativePtrDestructor)(GDNativeTypePtr p_base); -typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value); -typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value); -typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value); -typedef void (*GDNativePtrIndexedGetter)(const GDNativeTypePtr p_base, GDNativeInt p_index, GDNativeTypePtr r_value); -typedef void (*GDNativePtrKeyedSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_key, const GDNativeTypePtr p_value); -typedef void (*GDNativePtrKeyedGetter)(const GDNativeTypePtr p_base, const GDNativeTypePtr p_key, GDNativeTypePtr r_value); -typedef uint32_t (*GDNativePtrKeyedChecker)(const GDNativeVariantPtr p_base, const GDNativeVariantPtr p_key); -typedef void (*GDNativePtrUtilityFunction)(GDNativeTypePtr r_return, const GDNativeTypePtr *p_arguments, int p_argument_count); - -typedef GDNativeObjectPtr (*GDNativeClassConstructor)(); - -typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance); -typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding); -typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference); - -typedef struct { - GDNativeInstanceBindingCreateCallback create_callback; - GDNativeInstanceBindingFreeCallback free_callback; - GDNativeInstanceBindingReferenceCallback reference_callback; -} GDNativeInstanceBindingCallbacks; - -/* EXTENSION CLASSES */ - -typedef void *GDExtensionClassInstancePtr; - -typedef GDNativeBool (*GDNativeExtensionClassSet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value); -typedef GDNativeBool (*GDNativeExtensionClassGet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); -typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance); - -typedef struct { - GDNativeVariantType type; - const char *name; - const char *class_name; - uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`) - const char *hint_string; - uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`) -} GDNativePropertyInfo; - -typedef struct { - const char *name; - GDNativePropertyInfo return_value; - uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags` - int32_t id; - GDNativePropertyInfo *arguments; - uint32_t argument_count; - GDNativeVariantPtr default_arguments; - uint32_t default_argument_count; -} GDNativeMethodInfo; - -typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count); -typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list); -typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name); -typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); -typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); -typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out); -typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance); -typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); -typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); -typedef GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata); -typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); -typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name); - -typedef struct { - GDNativeBool is_virtual; - GDNativeBool is_abstract; - GDNativeExtensionClassSet set_func; - GDNativeExtensionClassGet get_func; - GDNativeExtensionClassGetPropertyList get_property_list_func; - GDNativeExtensionClassFreePropertyList free_property_list_func; - GDNativeExtensionClassPropertyCanRevert property_can_revert_func; - GDNativeExtensionClassPropertyGetRevert property_get_revert_func; - GDNativeExtensionClassNotification notification_func; - GDNativeExtensionClassToString to_string_func; - GDNativeExtensionClassReference reference_func; - GDNativeExtensionClassUnreference unreference_func; - GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ - GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ - GDNativeExtensionClassGetVirtual get_virtual_func; - GDNativeExtensionClassGetRID get_rid_func; - void *class_userdata; -} GDNativeExtensionClassCreationInfo; - -typedef void *GDNativeExtensionClassLibraryPtr; - -/* Method */ - -typedef enum { - GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL = 1, - GDNATIVE_EXTENSION_METHOD_FLAG_EDITOR = 2, - GDNATIVE_EXTENSION_METHOD_FLAG_CONST = 4, - GDNATIVE_EXTENSION_METHOD_FLAG_VIRTUAL = 8, - GDNATIVE_EXTENSION_METHOD_FLAG_VARARG = 16, - GDNATIVE_EXTENSION_METHOD_FLAG_STATIC = 32, - GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT = GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL, -} GDNativeExtensionClassMethodFlags; - -typedef enum { - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_NONE, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT8, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT16, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT8, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT16, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT, - GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE -} GDNativeExtensionClassMethodArgumentMetadata; - -typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); -typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); - -/* passing -1 as argument in the following functions refers to the return type */ -typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument); -typedef void (*GDNativeExtensionClassMethodGetArgumentInfo)(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info); -typedef GDNativeExtensionClassMethodArgumentMetadata (*GDNativeExtensionClassMethodGetArgumentMetadata)(void *p_method_userdata, int32_t p_argument); - -typedef struct { - const char *name; - void *method_userdata; - GDNativeExtensionClassMethodCall call_func; - GDNativeExtensionClassMethodPtrCall ptrcall_func; - uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags` - uint32_t argument_count; - GDNativeBool has_return_value; - GDNativeExtensionClassMethodGetArgumentType get_argument_type_func; - GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ - GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; - uint32_t default_argument_count; - GDNativeVariantPtr *default_arguments; -} GDNativeExtensionClassMethodInfo; - -/* SCRIPT INSTANCE EXTENSION */ - -typedef void *GDNativeExtensionScriptInstanceDataPtr; // Pointer to custom ScriptInstance native implementation - -typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value); -typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); -typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); -typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list); -typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid); - -typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name); -typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret); - -typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetOwner)(GDNativeExtensionScriptInstanceDataPtr p_instance); -typedef void (*GDNativeExtensionScriptInstancePropertyStateAdd)(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata); -typedef void (*GDNativeExtensionScriptInstanceGetPropertyState)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata); - -typedef const GDNativeMethodInfo *(*GDNativeExtensionScriptInstanceGetMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count); -typedef void (*GDNativeExtensionScriptInstanceFreeMethodList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeMethodInfo *p_list); - -typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name); - -typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); -typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what); -typedef const char *(*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid); - -typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); -typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetScript)(GDNativeExtensionScriptInstanceDataPtr p_instance); -typedef GDNativeBool (*GDNativeExtensionScriptInstanceIsPlaceholder)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef void *GDNativeExtensionScriptLanguagePtr; - -typedef GDNativeExtensionScriptLanguagePtr (*GDNativeExtensionScriptInstanceGetLanguage)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef void (*GDNativeExtensionScriptInstanceFree)(GDNativeExtensionScriptInstanceDataPtr p_instance); - -typedef void *GDNativeScriptInstancePtr; // Pointer to ScriptInstance. - -typedef struct { - GDNativeExtensionScriptInstanceSet set_func; - GDNativeExtensionScriptInstanceGet get_func; - GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func; - GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func; - GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func; - - GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func; - GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func; - - GDNativeExtensionScriptInstanceGetOwner get_owner_func; - GDNativeExtensionScriptInstanceGetPropertyState get_property_state_func; - - GDNativeExtensionScriptInstanceGetMethodList get_method_list_func; - GDNativeExtensionScriptInstanceFreeMethodList free_method_list_func; - - GDNativeExtensionScriptInstanceHasMethod has_method_func; - - GDNativeExtensionScriptInstanceCall call_func; - GDNativeExtensionScriptInstanceNotification notification_func; - - GDNativeExtensionScriptInstanceToString to_string_func; - - GDNativeExtensionScriptInstanceRefCountIncremented refcount_incremented_func; - GDNativeExtensionScriptInstanceRefCountDecremented refcount_decremented_func; - - GDNativeExtensionScriptInstanceGetScript get_script_func; - - GDNativeExtensionScriptInstanceIsPlaceholder is_placeholder_func; - - GDNativeExtensionScriptInstanceSet set_fallback_func; - GDNativeExtensionScriptInstanceGet get_fallback_func; - - GDNativeExtensionScriptInstanceGetLanguage get_language_func; - - GDNativeExtensionScriptInstanceFree free_func; - -} GDNativeExtensionScriptInstanceInfo; - -/* INTERFACE */ - -typedef struct { - uint32_t version_major; - uint32_t version_minor; - uint32_t version_patch; - const char *version_string; - - /* GODOT CORE */ - void *(*mem_alloc)(size_t p_bytes); - void *(*mem_realloc)(void *p_ptr, size_t p_bytes); - void (*mem_free)(void *p_ptr); - - void (*print_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - - uint64_t (*get_native_struct_size)(const char *p_name); - - /* GODOT VARIANT */ - - /* variant general */ - void (*variant_new_copy)(GDNativeVariantPtr r_dest, const GDNativeVariantPtr p_src); - void (*variant_new_nil)(GDNativeVariantPtr r_dest); - void (*variant_destroy)(GDNativeVariantPtr p_self); - - /* variant type */ - void (*variant_call)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); - void (*variant_call_static)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error); - void (*variant_evaluate)(GDNativeVariantOperator p_op, const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_return, GDNativeBool *r_valid); - void (*variant_set)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid); - void (*variant_set_named)(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid); - void (*variant_set_keyed)(GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, const GDNativeVariantPtr p_value, GDNativeBool *r_valid); - void (*variant_set_indexed)(GDNativeVariantPtr p_self, GDNativeInt p_index, const GDNativeVariantPtr p_value, GDNativeBool *r_valid, GDNativeBool *r_oob); - void (*variant_get)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - void (*variant_get_named)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - void (*variant_get_keyed)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - void (*variant_get_indexed)(const GDNativeVariantPtr p_self, GDNativeInt p_index, GDNativeVariantPtr r_ret, GDNativeBool *r_valid, GDNativeBool *r_oob); - GDNativeBool (*variant_iter_init)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid); - GDNativeBool (*variant_iter_next)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeBool *r_valid); - void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid); - GDNativeInt (*variant_hash)(const GDNativeVariantPtr p_self); - GDNativeInt (*variant_recursive_hash)(const GDNativeVariantPtr p_self, GDNativeInt p_recursion_count); - GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other); - GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self); - void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep); - void (*variant_stringify)(const GDNativeVariantPtr p_self, GDNativeStringPtr r_ret); - - GDNativeVariantType (*variant_get_type)(const GDNativeVariantPtr p_self); - GDNativeBool (*variant_has_method)(const GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method); - GDNativeBool (*variant_has_member)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); - GDNativeBool (*variant_has_key)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_key, GDNativeBool *r_valid); - void (*variant_get_type_name)(GDNativeVariantType p_type, GDNativeStringPtr r_name); - GDNativeBool (*variant_can_convert)(GDNativeVariantType p_from, GDNativeVariantType p_to); - GDNativeBool (*variant_can_convert_strict)(GDNativeVariantType p_from, GDNativeVariantType p_to); - - /* ptrcalls */ - GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type); - GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type); - GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b); - GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash); - GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor); - GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type); - void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error); - GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member); - GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member); - GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type); - GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type); - GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type); - GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type); - GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type); - void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret); - GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash); - - /* extra utilities */ - - void (*string_new_with_latin1_chars)(GDNativeStringPtr r_dest, const char *p_contents); - void (*string_new_with_utf8_chars)(GDNativeStringPtr r_dest, const char *p_contents); - void (*string_new_with_utf16_chars)(GDNativeStringPtr r_dest, const char16_t *p_contents); - void (*string_new_with_utf32_chars)(GDNativeStringPtr r_dest, const char32_t *p_contents); - void (*string_new_with_wide_chars)(GDNativeStringPtr r_dest, const wchar_t *p_contents); - void (*string_new_with_latin1_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size); - void (*string_new_with_utf8_chars_and_len)(GDNativeStringPtr r_dest, const char *p_contents, const GDNativeInt p_size); - void (*string_new_with_utf16_chars_and_len)(GDNativeStringPtr r_dest, const char16_t *p_contents, const GDNativeInt p_size); - void (*string_new_with_utf32_chars_and_len)(GDNativeStringPtr r_dest, const char32_t *p_contents, const GDNativeInt p_size); - void (*string_new_with_wide_chars_and_len)(GDNativeStringPtr r_dest, const wchar_t *p_contents, const GDNativeInt p_size); - /* Information about the following functions: - * - The return value is the resulting encoded string length. - * - The length returned is in characters, not in bytes. It also does not include a trailing zero. - * - These functions also do not write trailing zero, If you need it, write it yourself at the position indicated by the length (and make sure to allocate it). - * - Passing NULL in r_text means only the length is computed (again, without including trailing zero). - * - p_max_write_length argument is in characters, not bytes. It will be ignored if r_text is NULL. - * - p_max_write_length argument does not affect the return value, it's only to cap write length. - */ - GDNativeInt (*string_to_latin1_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_utf8_chars)(const GDNativeStringPtr p_self, char *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_utf16_chars)(const GDNativeStringPtr p_self, char16_t *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_utf32_chars)(const GDNativeStringPtr p_self, char32_t *r_text, GDNativeInt p_max_write_length); - GDNativeInt (*string_to_wide_chars)(const GDNativeStringPtr p_self, wchar_t *r_text, GDNativeInt p_max_write_length); - char32_t *(*string_operator_index)(GDNativeStringPtr p_self, GDNativeInt p_index); - const char32_t *(*string_operator_index_const)(const GDNativeStringPtr p_self, GDNativeInt p_index); - - /* Packed array functions */ - - uint8_t *(*packed_byte_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedByteArray - const uint8_t *(*packed_byte_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedByteArray - - GDNativeTypePtr (*packed_color_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedColorArray, returns Color ptr - GDNativeTypePtr (*packed_color_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedColorArray, returns Color ptr - - float *(*packed_float32_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat32Array - const float *(*packed_float32_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat32Array - double *(*packed_float64_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat64Array - const double *(*packed_float64_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedFloat64Array - - int32_t *(*packed_int32_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - const int32_t *(*packed_int32_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - int64_t *(*packed_int64_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - const int64_t *(*packed_int64_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedInt32Array - - GDNativeStringPtr (*packed_string_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedStringArray - GDNativeStringPtr (*packed_string_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedStringArray - - GDNativeTypePtr (*packed_vector2_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr - GDNativeTypePtr (*packed_vector2_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector2Array, returns Vector2 ptr - GDNativeTypePtr (*packed_vector3_array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr - GDNativeTypePtr (*packed_vector3_array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be a PackedVector3Array, returns Vector3 ptr - - GDNativeVariantPtr (*array_operator_index)(GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be an Array ptr - GDNativeVariantPtr (*array_operator_index_const)(const GDNativeTypePtr p_self, GDNativeInt p_index); // p_self should be an Array ptr - - /* Dictionary functions */ - - GDNativeVariantPtr (*dictionary_operator_index)(GDNativeTypePtr p_self, const GDNativeVariantPtr p_key); // p_self should be an Dictionary ptr - GDNativeVariantPtr (*dictionary_operator_index_const)(const GDNativeTypePtr p_self, const GDNativeVariantPtr p_key); // p_self should be an Dictionary ptr - - /* OBJECT */ - - void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error); - void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); - void (*object_destroy)(GDNativeObjectPtr p_o); - GDNativeObjectPtr (*global_get_singleton)(const char *p_name); - - void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks); - void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks); - - void (*object_set_instance)(GDNativeObjectPtr p_o, const char *p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ - - GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag); - GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); - GDObjectInstanceID (*object_get_instance_id)(const GDNativeObjectPtr p_object); - - /* SCRIPT INSTANCE */ - - GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data); - - /* CLASSDB */ - GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ - GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash); - void *(*classdb_get_class_tag)(const char *p_classname); - - /* CLASSDB EXTENSION */ - - void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); - void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); - void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); - void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); - void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); - void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */ - - void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); - -} GDNativeInterface; - -/* INITIALIZATION */ - -typedef enum { - GDNATIVE_INITIALIZATION_CORE, - GDNATIVE_INITIALIZATION_SERVERS, - GDNATIVE_INITIALIZATION_SCENE, - GDNATIVE_INITIALIZATION_EDITOR, - GDNATIVE_MAX_INITIALIZATION_LEVEL, -} GDNativeInitializationLevel; - -typedef struct { - /* Minimum initialization level required. - * If Core or Servers, the extension needs editor or game restart to take effect */ - GDNativeInitializationLevel minimum_initialization_level; - /* Up to the user to supply when initializing */ - void *userdata; - /* This function will be called multiple times for each initialization level. */ - void (*initialize)(void *userdata, GDNativeInitializationLevel p_level); - void (*deinitialize)(void *userdata, GDNativeInitializationLevel p_level); -} GDNativeInitialization; - -/* Define a C function prototype that implements the function below and expose it to dlopen() (or similar). - * It will be called on initialization. The name must be an unique one specified in the .gdextension config file. - */ - -typedef GDNativeBool (*GDNativeInitializationFunction)(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization); - -#ifdef __cplusplus -} -#endif - -#endif // GDNATIVE_INTERFACE_H diff --git a/core/extension/make_interface_dumper.py b/core/extension/make_interface_dumper.py index cc85c728d5..a8af0e9ff6 100644 --- a/core/extension/make_interface_dumper.py +++ b/core/extension/make_interface_dumper.py @@ -6,17 +6,17 @@ def run(target, source, env): g.write( """/* THIS FILE IS GENERATED DO NOT EDIT */ -#ifndef GDNATIVE_INTERFACE_DUMP_H -#define GDNATIVE_INTERFACE_DUMP_H +#ifndef GDEXTENSION_INTERFACE_DUMP_H +#define GDEXTENSION_INTERFACE_DUMP_H #ifdef TOOLS_ENABLED #include "core/io/file_access.h" #include "core/string/ustring.h" -class GDNativeInterfaceDump { +class GDExtensionInterfaceDump { private: - static constexpr char const *gdnative_interface_dump =""" + static constexpr char const *gdextension_interface_dump =""" ) for line in f: g.write('"' + line.rstrip().replace('"', '\\"') + '\\n"\n') @@ -25,16 +25,16 @@ class GDNativeInterfaceDump { g.write( """ public: - static void generate_gdnative_interface_file(const String &p_path) { + static void generate_gdextension_interface_file(const String &p_path) { Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE); - CharString cs(gdnative_interface_dump); + CharString cs(gdextension_interface_dump); fa->store_buffer((const uint8_t *)cs.ptr(), cs.length()); }; }; #endif // TOOLS_ENABLED -#endif // GDNATIVE_INTERFACE_DUMP_H +#endif // GDEXTENSION_INTERFACE_DUMP_H """ ) g.close() diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp deleted file mode 100644 index cc019584a5..0000000000 --- a/core/extension/native_extension.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/*************************************************************************/ -/* native_extension.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "native_extension.h" -#include "core/config/project_settings.h" -#include "core/io/config_file.h" -#include "core/object/class_db.h" -#include "core/object/method_bind.h" -#include "core/os/os.h" - -String NativeExtension::get_extension_list_config_file() { - return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg"); -} - -class NativeExtensionMethodBind : public MethodBind { - GDNativeExtensionClassMethodCall call_func; - GDNativeExtensionClassMethodPtrCall ptrcall_func; - GDNativeExtensionClassMethodGetArgumentType get_argument_type_func; - GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; - GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; - void *method_userdata; - bool vararg; - -protected: - virtual Variant::Type _gen_argument_type(int p_arg) const override { - return Variant::Type(get_argument_type_func(method_userdata, p_arg)); - } - virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { - GDNativePropertyInfo pinfo; - get_argument_info_func(method_userdata, p_arg, &pinfo); - return PropertyInfo(pinfo); - } - -public: -#ifdef DEBUG_METHODS_ENABLED - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { - return GodotTypeInfo::Metadata(get_argument_metadata_func(method_userdata, p_arg)); - } -#endif - - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) override { - Variant ret; - GDExtensionClassInstancePtr extension_instance = is_static() ? nullptr : p_object->_get_extension_instance(); - GDNativeCallError ce{ GDNATIVE_CALL_OK, 0, 0 }; - call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce); - r_error.error = Callable::CallError::Error(ce.error); - r_error.argument = ce.argument; - r_error.expected = ce.expected; - return ret; - } - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) override { - ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug."); - GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance(); - ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret); - } - - virtual bool is_vararg() const override { - return false; - } - - explicit NativeExtensionMethodBind(const GDNativeExtensionClassMethodInfo *p_method_info) { - method_userdata = p_method_info->method_userdata; - call_func = p_method_info->call_func; - ptrcall_func = p_method_info->ptrcall_func; - get_argument_type_func = p_method_info->get_argument_type_func; - get_argument_info_func = p_method_info->get_argument_info_func; - get_argument_metadata_func = p_method_info->get_argument_metadata_func; - set_name(p_method_info->name); - - set_hint_flags(p_method_info->method_flags); - - vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG; - _set_returns(p_method_info->has_return_value); - _set_const(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_CONST); - _set_static(p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_STATIC); -#ifdef DEBUG_METHODS_ENABLED - _generate_argument_types(p_method_info->argument_count); -#endif - set_argument_count(p_method_info->argument_count); - - Vector<Variant> defargs; - defargs.resize(p_method_info->default_argument_count); - for (uint32_t i = 0; i < p_method_info->default_argument_count; i++) { - defargs.write[i] = *static_cast<Variant *>(p_method_info->default_arguments[i]); - } - - set_default_arguments(defargs); - } -}; - -static GDNativeInterface gdnative_interface; - -void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier."); - ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered."); - - Extension *parent_extension = nullptr; - StringName parent_class_name = p_parent_class_name; - - if (self->extension_classes.has(parent_class_name)) { - parent_extension = &self->extension_classes[parent_class_name]; - } else if (ClassDB::class_exists(parent_class_name)) { - if (ClassDB::get_api_type(parent_class_name) == ClassDB::API_EXTENSION || ClassDB::get_api_type(parent_class_name) == ClassDB::API_EDITOR_EXTENSION) { - ERR_PRINT("Unimplemented yet"); - //inheriting from another extension - } else { - //inheriting from engine class - } - } else { - ERR_FAIL_MSG("Attempt to register an extension class '" + String(class_name) + "' using non-existing parent class '" + String(parent_class_name) + "'"); - } - - self->extension_classes[class_name] = Extension(); - - Extension *extension = &self->extension_classes[class_name]; - - if (parent_extension) { - extension->native_extension.parent = &parent_extension->native_extension; - parent_extension->native_extension.children.push_back(&extension->native_extension); - } - - extension->native_extension.parent_class_name = parent_class_name; - extension->native_extension.class_name = class_name; - extension->native_extension.editor_class = self->level_initialized == INITIALIZATION_LEVEL_EDITOR; - extension->native_extension.is_virtual = p_extension_funcs->is_virtual; - extension->native_extension.is_abstract = p_extension_funcs->is_abstract; - extension->native_extension.set = p_extension_funcs->set_func; - extension->native_extension.get = p_extension_funcs->get_func; - extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func; - extension->native_extension.free_property_list = p_extension_funcs->free_property_list_func; - extension->native_extension.property_can_revert = p_extension_funcs->property_can_revert_func; - extension->native_extension.property_get_revert = p_extension_funcs->property_get_revert_func; - extension->native_extension.notification = p_extension_funcs->notification_func; - extension->native_extension.to_string = p_extension_funcs->to_string_func; - extension->native_extension.reference = p_extension_funcs->reference_func; - extension->native_extension.unreference = p_extension_funcs->unreference_func; - extension->native_extension.class_userdata = p_extension_funcs->class_userdata; - extension->native_extension.create_instance = p_extension_funcs->create_instance_func; - extension->native_extension.free_instance = p_extension_funcs->free_instance_func; - extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func; - extension->native_extension.get_rid = p_extension_funcs->get_rid_func; - - ClassDB::register_extension_class(&extension->native_extension); -} -void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - StringName method_name = p_method_info->name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'."); - - //Extension *extension = &self->extension_classes[class_name]; - - NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info)); - method->set_instance_class(class_name); - - ClassDB::bind_method_custom(class_name, method); -} -void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'."); - - //Extension *extension = &self->extension_classes[class_name]; - - ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield); -} - -void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - String property_name = p_info->name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'."); - - //Extension *extension = &self->extension_classes[class_name]; - PropertyInfo pinfo(*p_info); - - ClassDB::add_property(class_name, pinfo, p_setter, p_getter); -} - -void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + String(p_group_name) + "' for unexisting class '" + class_name + "'."); - - ClassDB::add_property_group(class_name, p_group_name, p_prefix); -} - -void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + String(p_subgroup_name) + "' for unexisting class '" + class_name + "'."); - - ClassDB::add_property_subgroup(class_name, p_subgroup_name, p_prefix); -} - -void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'."); - - MethodInfo s; - s.name = p_signal_name; - for (int i = 0; i < p_argument_count; i++) { - PropertyInfo arg(p_argument_info[i]); - s.arguments.push_back(arg); - } - ClassDB::add_signal(class_name, s); -} - -void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - StringName class_name = p_class_name; - ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'."); - Extension *ext = &self->extension_classes[class_name]; - ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it."); - - ClassDB::unregister_extension_class(class_name); - if (ext->native_extension.parent != nullptr) { - ext->native_extension.parent->children.erase(&ext->native_extension); - } - self->extension_classes.erase(class_name); -} - -void NativeExtension::_get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path) { - NativeExtension *self = static_cast<NativeExtension *>(p_library); - - *(String *)r_path = self->library_path; -} - -Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) { - Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true, &library_path); - if (err != OK) { - ERR_PRINT("GDExtension dynamic library not found: " + p_path); - return err; - } - - void *entry_funcptr = nullptr; - - err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false); - - if (err != OK) { - ERR_PRINT("GDExtension entry point '" + p_entry_symbol + "' not found in library " + p_path); - OS::get_singleton()->close_dynamic_library(library); - return err; - } - - GDNativeInitializationFunction initialization_function = (GDNativeInitializationFunction)entry_funcptr; - - if (initialization_function(&gdnative_interface, this, &initialization)) { - level_initialized = -1; - return OK; - } else { - ERR_PRINT("GDExtension initialization function '" + p_entry_symbol + "' returned an error."); - return FAILED; - } -} - -void NativeExtension::close_library() { - ERR_FAIL_COND(library == nullptr); - OS::get_singleton()->close_dynamic_library(library); - - library = nullptr; -} - -bool NativeExtension::is_library_open() const { - return library != nullptr; -} - -NativeExtension::InitializationLevel NativeExtension::get_minimum_library_initialization_level() const { - ERR_FAIL_COND_V(library == nullptr, INITIALIZATION_LEVEL_CORE); - return InitializationLevel(initialization.minimum_initialization_level); -} - -void NativeExtension::initialize_library(InitializationLevel p_level) { - ERR_FAIL_COND(library == nullptr); - ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized)); - - level_initialized = int32_t(p_level); - - ERR_FAIL_COND(initialization.initialize == nullptr); - - initialization.initialize(initialization.userdata, GDNativeInitializationLevel(p_level)); -} -void NativeExtension::deinitialize_library(InitializationLevel p_level) { - ERR_FAIL_COND(library == nullptr); - ERR_FAIL_COND(p_level > int32_t(level_initialized)); - - level_initialized = int32_t(p_level) - 1; - initialization.deinitialize(initialization.userdata, GDNativeInitializationLevel(p_level)); -} - -void NativeExtension::_bind_methods() { - ClassDB::bind_method(D_METHOD("open_library", "path", "entry_symbol"), &NativeExtension::open_library); - ClassDB::bind_method(D_METHOD("close_library"), &NativeExtension::close_library); - ClassDB::bind_method(D_METHOD("is_library_open"), &NativeExtension::is_library_open); - - ClassDB::bind_method(D_METHOD("get_minimum_library_initialization_level"), &NativeExtension::get_minimum_library_initialization_level); - ClassDB::bind_method(D_METHOD("initialize_library", "level"), &NativeExtension::initialize_library); - - BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_CORE); - BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SERVERS); - BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_SCENE); - BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR); -} - -NativeExtension::NativeExtension() { -} - -NativeExtension::~NativeExtension() { - if (library != nullptr) { - close_library(); - } -} - -extern void gdnative_setup_interface(GDNativeInterface *p_interface); - -void NativeExtension::initialize_native_extensions() { - gdnative_setup_interface(&gdnative_interface); - - gdnative_interface.classdb_register_extension_class = _register_extension_class; - gdnative_interface.classdb_register_extension_class_method = _register_extension_class_method; - gdnative_interface.classdb_register_extension_class_integer_constant = _register_extension_class_integer_constant; - gdnative_interface.classdb_register_extension_class_property = _register_extension_class_property; - gdnative_interface.classdb_register_extension_class_property_group = _register_extension_class_property_group; - gdnative_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup; - gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal; - gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class; - gdnative_interface.get_library_path = _get_library_path; -} - -Ref<Resource> NativeExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { - Ref<ConfigFile> config; - config.instantiate(); - - Error err = config->load(p_path); - - if (r_error) { - *r_error = err; - } - - if (err != OK) { - ERR_PRINT("Error loading GDExtension configuration file: " + p_path); - return Ref<Resource>(); - } - - if (!config->has_section_key("configuration", "entry_symbol")) { - if (r_error) { - *r_error = ERR_INVALID_DATA; - } - ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path); - return Ref<Resource>(); - } - - String entry_symbol = config->get_value("configuration", "entry_symbol"); - - List<String> libraries; - - config->get_section_keys("libraries", &libraries); - - String library_path; - - for (const String &E : libraries) { - Vector<String> tags = E.split("."); - bool all_tags_met = true; - for (int i = 0; i < tags.size(); i++) { - String tag = tags[i].strip_edges(); - if (!OS::get_singleton()->has_feature(tag)) { - all_tags_met = false; - break; - } - } - - if (all_tags_met) { - library_path = config->get_value("libraries", E); - break; - } - } - - if (library_path.is_empty()) { - if (r_error) { - *r_error = ERR_FILE_NOT_FOUND; - } - const String os_arch = OS::get_singleton()->get_name().to_lower() + "." + Engine::get_singleton()->get_architecture_name(); - ERR_PRINT(vformat("No GDExtension library found for current OS and architecture (%s) in configuration file: %s", os_arch, p_path)); - return Ref<Resource>(); - } - - if (!library_path.is_resource_file() && !library_path.is_absolute_path()) { - library_path = p_path.get_base_dir().path_join(library_path); - } - - Ref<NativeExtension> lib; - lib.instantiate(); - String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path); - err = lib->open_library(abs_path, entry_symbol); - - if (r_error) { - *r_error = err; - } - - if (err != OK) { - // Errors already logged in open_library() - return Ref<Resource>(); - } - - return lib; -} - -void NativeExtensionResourceLoader::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("gdextension"); -} - -bool NativeExtensionResourceLoader::handles_type(const String &p_type) const { - return p_type == "NativeExtension"; -} - -String NativeExtensionResourceLoader::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "gdextension") { - return "NativeExtension"; - } - return ""; -} diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h deleted file mode 100644 index b7238d2899..0000000000 --- a/core/extension/native_extension.h +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************/ -/* native_extension.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef NATIVE_EXTENSION_H -#define NATIVE_EXTENSION_H - -#include "core/extension/gdnative_interface.h" -#include "core/io/resource_loader.h" -#include "core/object/ref_counted.h" - -class NativeExtension : public Resource { - GDCLASS(NativeExtension, Resource) - - void *library = nullptr; // pointer if valid, - String library_path; - - struct Extension { - ObjectNativeExtension native_extension; - }; - - HashMap<StringName, Extension> extension_classes; - - static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs); - static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info); - static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield); - static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter); - static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix); - static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix); - static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count); - static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); - static void _get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path); - - GDNativeInitialization initialization; - int32_t level_initialized = -1; - -protected: - static void _bind_methods(); - -public: - static String get_extension_list_config_file(); - - Error open_library(const String &p_path, const String &p_entry_symbol); - void close_library(); - - enum InitializationLevel { - INITIALIZATION_LEVEL_CORE = GDNATIVE_INITIALIZATION_CORE, - INITIALIZATION_LEVEL_SERVERS = GDNATIVE_INITIALIZATION_SERVERS, - INITIALIZATION_LEVEL_SCENE = GDNATIVE_INITIALIZATION_SCENE, - INITIALIZATION_LEVEL_EDITOR = GDNATIVE_INITIALIZATION_EDITOR - }; - - bool is_library_open() const; - - InitializationLevel get_minimum_library_initialization_level() const; - void initialize_library(InitializationLevel p_level); - void deinitialize_library(InitializationLevel p_level); - - static void initialize_native_extensions(); - NativeExtension(); - ~NativeExtension(); -}; - -VARIANT_ENUM_CAST(NativeExtension::InitializationLevel) - -class NativeExtensionResourceLoader : public ResourceFormatLoader { -public: - virtual Ref<Resource> load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE); - virtual void get_recognized_extensions(List<String> *p_extensions) const; - virtual bool handles_type(const String &p_type) const; - virtual String get_resource_type(const String &p_path) const; -}; - -#endif // NATIVE_EXTENSION_H diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp deleted file mode 100644 index 186fcc44f6..0000000000 --- a/core/extension/native_extension_manager.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/*************************************************************************/ -/* native_extension_manager.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "native_extension_manager.h" -#include "core/io/file_access.h" - -NativeExtensionManager::LoadStatus NativeExtensionManager::load_extension(const String &p_path) { - if (native_extension_map.has(p_path)) { - return LOAD_STATUS_ALREADY_LOADED; - } - Ref<NativeExtension> extension = ResourceLoader::load(p_path); - if (extension.is_null()) { - return LOAD_STATUS_FAILED; - } - - if (level >= 0) { // Already initialized up to some level. - int32_t minimum_level = extension->get_minimum_library_initialization_level(); - if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) { - return LOAD_STATUS_NEEDS_RESTART; - } - // Initialize up to current level. - for (int32_t i = minimum_level; i <= level; i++) { - extension->initialize_library(NativeExtension::InitializationLevel(i)); - } - } - native_extension_map[p_path] = extension; - return LOAD_STATUS_OK; -} - -NativeExtensionManager::LoadStatus NativeExtensionManager::reload_extension(const String &p_path) { - return LOAD_STATUS_OK; //TODO -} -NativeExtensionManager::LoadStatus NativeExtensionManager::unload_extension(const String &p_path) { - if (!native_extension_map.has(p_path)) { - return LOAD_STATUS_NOT_LOADED; - } - - Ref<NativeExtension> extension = native_extension_map[p_path]; - - if (level >= 0) { // Already initialized up to some level. - int32_t minimum_level = extension->get_minimum_library_initialization_level(); - if (minimum_level < MIN(level, NativeExtension::INITIALIZATION_LEVEL_SCENE)) { - return LOAD_STATUS_NEEDS_RESTART; - } - // Deinitialize down to current level. - for (int32_t i = level; i >= minimum_level; i--) { - extension->deinitialize_library(NativeExtension::InitializationLevel(i)); - } - } - native_extension_map.erase(p_path); - return LOAD_STATUS_OK; -} - -bool NativeExtensionManager::is_extension_loaded(const String &p_path) const { - return native_extension_map.has(p_path); -} - -Vector<String> NativeExtensionManager::get_loaded_extensions() const { - Vector<String> ret; - for (const KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) { - ret.push_back(E.key); - } - return ret; -} -Ref<NativeExtension> NativeExtensionManager::get_extension(const String &p_path) { - HashMap<String, Ref<NativeExtension>>::Iterator E = native_extension_map.find(p_path); - ERR_FAIL_COND_V(!E, Ref<NativeExtension>()); - return E->value; -} - -void NativeExtensionManager::initialize_extensions(NativeExtension::InitializationLevel p_level) { - ERR_FAIL_COND(int32_t(p_level) - 1 != level); - for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) { - E.value->initialize_library(p_level); - } - level = p_level; -} - -void NativeExtensionManager::deinitialize_extensions(NativeExtension::InitializationLevel p_level) { - ERR_FAIL_COND(int32_t(p_level) != level); - for (KeyValue<String, Ref<NativeExtension>> &E : native_extension_map) { - E.value->deinitialize_library(p_level); - } - level = int32_t(p_level) - 1; -} - -void NativeExtensionManager::load_extensions() { - Ref<FileAccess> f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ); - while (f.is_valid() && !f->eof_reached()) { - String s = f->get_line().strip_edges(); - if (!s.is_empty()) { - LoadStatus err = load_extension(s); - ERR_CONTINUE_MSG(err == LOAD_STATUS_FAILED, "Error loading extension: " + s); - } - } -} - -NativeExtensionManager *NativeExtensionManager::get_singleton() { - return singleton; -} -void NativeExtensionManager::_bind_methods() { - ClassDB::bind_method(D_METHOD("load_extension", "path"), &NativeExtensionManager::load_extension); - ClassDB::bind_method(D_METHOD("reload_extension", "path"), &NativeExtensionManager::reload_extension); - ClassDB::bind_method(D_METHOD("unload_extension", "path"), &NativeExtensionManager::unload_extension); - ClassDB::bind_method(D_METHOD("is_extension_loaded", "path"), &NativeExtensionManager::is_extension_loaded); - - ClassDB::bind_method(D_METHOD("get_loaded_extensions"), &NativeExtensionManager::get_loaded_extensions); - ClassDB::bind_method(D_METHOD("get_extension", "path"), &NativeExtensionManager::get_extension); - - BIND_ENUM_CONSTANT(LOAD_STATUS_OK); - BIND_ENUM_CONSTANT(LOAD_STATUS_FAILED); - BIND_ENUM_CONSTANT(LOAD_STATUS_ALREADY_LOADED); - BIND_ENUM_CONSTANT(LOAD_STATUS_NOT_LOADED); - BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART); -} - -NativeExtensionManager *NativeExtensionManager::singleton = nullptr; - -NativeExtensionManager::NativeExtensionManager() { - ERR_FAIL_COND(singleton != nullptr); - singleton = this; -} |