summaryrefslogtreecommitdiff
path: root/core/extension
diff options
context:
space:
mode:
Diffstat (limited to 'core/extension')
-rw-r--r--core/extension/SCsub13
-rw-r--r--core/extension/extension_api_dump.cpp926
-rw-r--r--core/extension/extension_api_dump.h45
-rw-r--r--core/extension/gdnative_interface.cpp1098
-rw-r--r--core/extension/gdnative_interface.h585
-rw-r--r--core/extension/make_wrappers.py93
-rw-r--r--core/extension/native_extension.cpp455
-rw-r--r--core/extension/native_extension.h100
-rw-r--r--core/extension/native_extension_manager.cpp149
-rw-r--r--core/extension/native_extension_manager.h74
10 files changed, 3538 insertions, 0 deletions
diff --git a/core/extension/SCsub b/core/extension/SCsub
new file mode 100644
index 0000000000..23727c1b76
--- /dev/null
+++ b/core/extension/SCsub
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+Import("env")
+
+import make_wrappers
+from platform_methods import run_in_subprocess
+
+env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", run_in_subprocess(make_wrappers.run))
+
+
+env_extension = env.Clone()
+
+env_extension.add_source_files(env.core_sources, "*.cpp")
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
new file mode 100644
index 0000000000..867b1fc637
--- /dev/null
+++ b/core/extension/extension_api_dump.cpp
@@ -0,0 +1,926 @@
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
+#include "extension_api_dump.h"
+#include "core/config/engine.h"
+#include "core/core_constants.h"
+#include "core/io/file_access.h"
+#include "core/io/json.h"
+#include "core/templates/pair.h"
+#include "core/version.h"
+
+#ifdef TOOLS_ENABLED
+
+static String get_type_name(const PropertyInfo &p_info) {
+ if (p_info.type == Variant::INT && (p_info.hint == PROPERTY_HINT_INT_IS_POINTER)) {
+ if (p_info.hint_string.is_empty()) {
+ return "void*";
+ } else {
+ return p_info.hint_string + "*";
+ }
+ }
+ if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM))) {
+ return String("enum::") + String(p_info.class_name);
+ }
+ if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_BITFIELD))) {
+ return String("bitfield::") + String(p_info.class_name);
+ }
+ if (p_info.class_name != StringName()) {
+ return p_info.class_name;
+ }
+ if (p_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ return p_info.hint_string;
+ }
+ if (p_info.type == Variant::NIL && (p_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) {
+ return "Variant";
+ }
+ if (p_info.type == Variant::NIL) {
+ return "void";
+ }
+ return Variant::get_type_name(p_info.type);
+}
+
+Dictionary NativeExtensionAPIDump::generate_extension_api() {
+ Dictionary api_dump;
+
+ {
+ //header
+ Dictionary header;
+ header["version_major"] = VERSION_MAJOR;
+ header["version_minor"] = VERSION_MINOR;
+#if VERSION_PATCH
+ header["version_patch"] = VERSION_PATCH;
+#else
+ header["version_patch"] = 0;
+#endif
+ header["version_status"] = VERSION_STATUS;
+ header["version_build"] = VERSION_BUILD;
+ header["version_full_name"] = VERSION_FULL_NAME;
+
+ api_dump["header"] = header;
+ }
+
+ const uint32_t vec3_elems = 3;
+ const uint32_t ptrsize_32 = 4;
+ const uint32_t ptrsize_64 = 8;
+ static const char *build_config_name[4] = { "float_32", "float_64", "double_32", "double_64" };
+
+ {
+ //type sizes
+ constexpr struct {
+ Variant::Type type;
+ uint32_t size_32_bits_real_float;
+ uint32_t size_64_bits_real_float;
+ uint32_t size_32_bits_real_double;
+ uint32_t size_64_bits_real_double;
+
+ // For compile-time size check.
+ constexpr uint32_t operator[](int index) const {
+ switch (index) {
+#ifndef REAL_T_IS_DOUBLE
+ case sizeof(uint32_t):
+ return size_32_bits_real_float;
+ case sizeof(uint64_t):
+ return size_64_bits_real_float;
+#else // REAL_T_IS_DOUBLE
+ case sizeof(uint32_t):
+ return size_32_bits_real_double;
+ case sizeof(uint64_t):
+ return size_64_bits_real_double;
+#endif
+ }
+ return -1;
+ }
+ } type_size_array[Variant::VARIANT_MAX + 1] = {
+ { Variant::NIL, 0, 0, 0, 0 },
+ { Variant::BOOL, sizeof(uint8_t), sizeof(uint8_t), sizeof(uint8_t), sizeof(uint8_t) },
+ { Variant::INT, sizeof(int64_t), sizeof(int64_t), sizeof(int64_t), sizeof(int64_t) },
+ { Variant::FLOAT, sizeof(double), sizeof(double), sizeof(double), sizeof(double) },
+ { Variant::STRING, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::VECTOR2, 2 * sizeof(float), 2 * sizeof(float), 2 * sizeof(double), 2 * sizeof(double) },
+ { Variant::VECTOR2I, 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t), 2 * sizeof(int32_t) },
+ { Variant::RECT2, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::RECT2I, 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t) },
+ { Variant::VECTOR3, vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
+ { Variant::VECTOR3I, 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t), 3 * sizeof(int32_t) },
+ { Variant::TRANSFORM2D, 6 * sizeof(float), 6 * sizeof(float), 6 * sizeof(double), 6 * sizeof(double) },
+ { Variant::VECTOR4, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::VECTOR4I, 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t), 4 * sizeof(int32_t) },
+ { Variant::PLANE, (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(float), (vec3_elems + 1) * sizeof(double), (vec3_elems + 1) * sizeof(double) },
+ { Variant::QUATERNION, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(double), 4 * sizeof(double) },
+ { Variant::AABB, (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(float), (vec3_elems * 2) * sizeof(double), (vec3_elems * 2) * sizeof(double) },
+ { Variant::BASIS, (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(float), (vec3_elems * 3) * sizeof(double), (vec3_elems * 3) * sizeof(double) },
+ { Variant::TRANSFORM3D, (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(float), (vec3_elems * 4) * sizeof(double), (vec3_elems * 4) * sizeof(double) },
+ { Variant::PROJECTION, 4 * 4 * sizeof(float), 4 * 4 * sizeof(float), 4 * 4 * sizeof(double), 4 * 4 * sizeof(double) },
+ { Variant::COLOR, 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float), 4 * sizeof(float) },
+ { Variant::STRING_NAME, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::NODE_PATH, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::RID, sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t) },
+ { Variant::OBJECT, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::CALLABLE, sizeof(Callable), sizeof(Callable), sizeof(Callable), sizeof(Callable) }, // Hardcoded align.
+ { Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, // Hardcoded align.
+ { Variant::DICTIONARY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_BYTE_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_INT32_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_INT64_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_FLOAT32_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_FLOAT64_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_STRING_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_COLOR_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::VARIANT_MAX, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(double) * 4, sizeof(uint64_t) + sizeof(double) * 4 },
+ };
+
+ // 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::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");
+ static_assert(type_size_array[Variant::VECTOR2I][sizeof(void *)] == sizeof(Vector2i), "Size of Vector2i mismatch");
+ static_assert(type_size_array[Variant::RECT2][sizeof(void *)] == sizeof(Rect2), "Size of Rect2 mismatch");
+ static_assert(type_size_array[Variant::RECT2I][sizeof(void *)] == sizeof(Rect2i), "Size of Rect2i mismatch");
+ static_assert(type_size_array[Variant::VECTOR3][sizeof(void *)] == sizeof(Vector3), "Size of Vector3 mismatch");
+ static_assert(type_size_array[Variant::VECTOR3I][sizeof(void *)] == sizeof(Vector3i), "Size of Vector3i mismatch");
+ static_assert(type_size_array[Variant::TRANSFORM2D][sizeof(void *)] == sizeof(Transform2D), "Size of Transform2D mismatch");
+ static_assert(type_size_array[Variant::VECTOR4][sizeof(void *)] == sizeof(Vector4), "Size of Vector4 mismatch");
+ static_assert(type_size_array[Variant::VECTOR4I][sizeof(void *)] == sizeof(Vector4i), "Size of Vector4i mismatch");
+ static_assert(type_size_array[Variant::PLANE][sizeof(void *)] == sizeof(Plane), "Size of Plane mismatch");
+ static_assert(type_size_array[Variant::QUATERNION][sizeof(void *)] == sizeof(Quaternion), "Size of Quaternion mismatch");
+ static_assert(type_size_array[Variant::AABB][sizeof(void *)] == sizeof(AABB), "Size of AABB mismatch");
+ static_assert(type_size_array[Variant::BASIS][sizeof(void *)] == sizeof(Basis), "Size of Basis mismatch");
+ static_assert(type_size_array[Variant::TRANSFORM3D][sizeof(void *)] == sizeof(Transform3D), "Size of Transform3D mismatch");
+ static_assert(type_size_array[Variant::PROJECTION][sizeof(void *)] == sizeof(Projection), "Size of Projection mismatch");
+ static_assert(type_size_array[Variant::COLOR][sizeof(void *)] == sizeof(Color), "Size of Color mismatch");
+ static_assert(type_size_array[Variant::STRING_NAME][sizeof(void *)] == sizeof(StringName), "Size of StringName mismatch");
+ static_assert(type_size_array[Variant::NODE_PATH][sizeof(void *)] == sizeof(NodePath), "Size of NodePath mismatch");
+ static_assert(type_size_array[Variant::RID][sizeof(void *)] == sizeof(RID), "Size of RID mismatch");
+ static_assert(type_size_array[Variant::OBJECT][sizeof(void *)] == sizeof(Object *), "Size of Object mismatch");
+ static_assert(type_size_array[Variant::CALLABLE][sizeof(void *)] == sizeof(Callable), "Size of Callable mismatch");
+ static_assert(type_size_array[Variant::SIGNAL][sizeof(void *)] == sizeof(Signal), "Size of Signal mismatch");
+ static_assert(type_size_array[Variant::DICTIONARY][sizeof(void *)] == sizeof(Dictionary), "Size of Dictionary mismatch");
+ static_assert(type_size_array[Variant::ARRAY][sizeof(void *)] == sizeof(Array), "Size of Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_BYTE_ARRAY][sizeof(void *)] == sizeof(PackedByteArray), "Size of PackedByteArray mismatch");
+ static_assert(type_size_array[Variant::PACKED_INT32_ARRAY][sizeof(void *)] == sizeof(PackedInt32Array), "Size of PackedInt32Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_INT64_ARRAY][sizeof(void *)] == sizeof(PackedInt64Array), "Size of PackedInt64Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_FLOAT32_ARRAY][sizeof(void *)] == sizeof(PackedFloat32Array), "Size of PackedFloat32Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_FLOAT64_ARRAY][sizeof(void *)] == sizeof(PackedFloat64Array), "Size of PackedFloat64Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_STRING_ARRAY][sizeof(void *)] == sizeof(PackedStringArray), "Size of PackedStringArray mismatch");
+ static_assert(type_size_array[Variant::PACKED_VECTOR2_ARRAY][sizeof(void *)] == sizeof(PackedVector2Array), "Size of PackedVector2Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_VECTOR3_ARRAY][sizeof(void *)] == sizeof(PackedVector3Array), "Size of PackedVector3Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_COLOR_ARRAY][sizeof(void *)] == sizeof(PackedColorArray), "Size of PackedColorArray mismatch");
+ static_assert(type_size_array[Variant::VARIANT_MAX][sizeof(void *)] == sizeof(Variant), "Size of Variant mismatch");
+
+ Array core_type_sizes;
+
+ for (int i = 0; i < 4; i++) {
+ Dictionary d;
+ d["build_configuration"] = build_config_name[i];
+ Array sizes;
+ for (int j = 0; j <= Variant::VARIANT_MAX; j++) {
+ Variant::Type t = type_size_array[j].type;
+ String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
+ Dictionary d2;
+ d2["name"] = name;
+ uint32_t size;
+ switch (i) {
+ case 0:
+ size = type_size_array[j].size_32_bits_real_float;
+ break;
+ case 1:
+ size = type_size_array[j].size_64_bits_real_float;
+ break;
+ case 2:
+ size = type_size_array[j].size_32_bits_real_double;
+ break;
+ case 3:
+ size = type_size_array[j].size_64_bits_real_double;
+ break;
+ }
+ d2["size"] = size;
+ sizes.push_back(d2);
+ }
+ d["sizes"] = sizes;
+ core_type_sizes.push_back(d);
+ }
+ api_dump["builtin_class_sizes"] = core_type_sizes;
+ }
+
+ {
+ // Member offsets sizes.
+ 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;
+ } 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::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 },
+ };
+
+ Array core_type_member_offsets;
+
+ for (int i = 0; i < 4; i++) {
+ Dictionary d;
+ d["build_configuration"] = build_config_name[i];
+ Array type_offsets;
+ uint32_t idx = 0;
+
+ Variant::Type last_type = Variant::NIL;
+
+ Dictionary d2;
+ Array members;
+
+ while (true) {
+ Variant::Type t = member_offset_array[idx].type;
+ if (t != last_type) {
+ if (last_type != Variant::NIL) {
+ d2["members"] = members;
+ type_offsets.push_back(d2);
+ }
+ if (t == Variant::NIL) {
+ break;
+ }
+
+ String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
+ d2 = Dictionary();
+ members = Array();
+ d2["name"] = name;
+ last_type = t;
+ }
+ Dictionary d3;
+ uint32_t offset;
+ switch (i) {
+ case 0:
+ offset = member_offset_array[idx].offset_32_bits_real_float;
+ break;
+ case 1:
+ offset = member_offset_array[idx].offset_64_bits_real_float;
+ break;
+ case 2:
+ offset = member_offset_array[idx].offset_32_bits_real_double;
+ break;
+ case 3:
+ offset = member_offset_array[idx].offset_64_bits_real_double;
+ break;
+ }
+ d3["member"] = member_offset_array[idx].member;
+ d3["offset"] = offset;
+ members.push_back(d3);
+ idx++;
+ }
+ d["classes"] = type_offsets;
+ core_type_member_offsets.push_back(d);
+ }
+ api_dump["builtin_class_member_offsets"] = core_type_member_offsets;
+ }
+
+ {
+ // Global enums and constants.
+ Array constants;
+ HashMap<String, List<Pair<String, int64_t>>> enum_list;
+
+ 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);
+ if (!enum_name.is_empty()) {
+ enum_list[enum_name].push_back(Pair<String, int64_t>(name, value));
+ } else {
+ Dictionary d;
+ d["name"] = name;
+ d["value"] = value;
+ constants.push_back(d);
+ }
+ }
+
+ api_dump["global_constants"] = constants;
+
+ Array enums;
+ for (const KeyValue<String, List<Pair<String, int64_t>>> &E : enum_list) {
+ Dictionary d1;
+ d1["name"] = E.key;
+ Array values;
+ for (const Pair<String, int64_t> &F : E.value) {
+ Dictionary d2;
+ d2["name"] = F.first;
+ d2["value"] = F.second;
+ values.push_back(d2);
+ }
+ d1["values"] = values;
+ enums.push_back(d1);
+ }
+
+ api_dump["global_enums"] = enums;
+ }
+ {
+ Array utility_funcs;
+
+ List<StringName> utility_func_names;
+ Variant::get_utility_function_list(&utility_func_names);
+
+ for (const StringName &name : utility_func_names) {
+ Dictionary func;
+ func["name"] = String(name);
+ if (Variant::has_utility_function_return_value(name)) {
+ Variant::Type rt = Variant::get_utility_function_return_type(name);
+ func["return_type"] = rt == Variant::NIL ? String("Variant") : Variant::get_type_name(rt);
+ }
+ switch (Variant::get_utility_function_type(name)) {
+ case Variant::UTILITY_FUNC_TYPE_MATH:
+ func["category"] = "math";
+ break;
+ case Variant::UTILITY_FUNC_TYPE_RANDOM:
+ func["category"] = "random";
+ break;
+ case Variant::UTILITY_FUNC_TYPE_GENERAL:
+ func["category"] = "general";
+ break;
+ }
+ bool vararg = Variant::is_utility_function_vararg(name);
+ func["is_vararg"] = Variant::is_utility_function_vararg(name);
+ func["hash"] = Variant::get_utility_function_hash(name);
+ Array arguments;
+ int argcount = Variant::get_utility_function_argument_count(name);
+ for (int i = 0; i < argcount; i++) {
+ Dictionary arg;
+ String argname = vararg ? "arg" + itos(i + 1) : Variant::get_utility_function_argument_name(name, i);
+ arg["name"] = argname;
+ Variant::Type argtype = Variant::get_utility_function_argument_type(name, i);
+ arg["type"] = argtype == Variant::NIL ? String("Variant") : Variant::get_type_name(argtype);
+ //no default value support in utility functions
+ arguments.push_back(arg);
+ }
+
+ if (arguments.size()) {
+ func["arguments"] = arguments;
+ }
+
+ utility_funcs.push_back(func);
+ }
+
+ api_dump["utility_functions"] = utility_funcs;
+ }
+
+ {
+ // builtin types
+
+ Array builtins;
+
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (i == Variant::OBJECT) {
+ continue;
+ }
+
+ Variant::Type type = Variant::Type(i);
+
+ Dictionary d;
+ d["name"] = Variant::get_type_name(type);
+ if (Variant::has_indexing(type)) {
+ Variant::Type index_type = Variant::get_indexed_element_type(type);
+ d["indexing_return_type"] = index_type == Variant::NIL ? String("Variant") : Variant::get_type_name(index_type);
+ }
+
+ d["is_keyed"] = Variant::ValidatedKeyedSetter(type);
+
+ {
+ //members
+ Array members;
+
+ List<StringName> member_names;
+ Variant::get_member_list(type, &member_names);
+ for (const StringName &member_name : member_names) {
+ Dictionary d2;
+ d2["name"] = String(member_name);
+ d2["type"] = Variant::get_type_name(Variant::get_member_type(type, member_name));
+ members.push_back(d2);
+ }
+ if (members.size()) {
+ d["members"] = members;
+ }
+ }
+ {
+ //constants
+ Array constants;
+
+ List<StringName> constant_names;
+ Variant::get_constants_for_type(type, &constant_names);
+ for (const StringName &constant_name : constant_names) {
+ Dictionary d2;
+ d2["name"] = String(constant_name);
+ Variant constant = Variant::get_constant_value(type, constant_name);
+ d2["type"] = Variant::get_type_name(constant.get_type());
+ d2["value"] = constant.get_construct_string();
+ constants.push_back(d2);
+ }
+ if (constants.size()) {
+ d["constants"] = constants;
+ }
+ }
+ {
+ //enums
+ Array enums;
+
+ List<StringName> enum_names;
+ Variant::get_enums_for_type(type, &enum_names);
+ for (const StringName &enum_name : enum_names) {
+ Dictionary enum_dict;
+ enum_dict["name"] = String(enum_name);
+
+ List<StringName> enumeration_names;
+ Variant::get_enumerations_for_enum(type, enum_name, &enumeration_names);
+
+ Array values;
+
+ for (const StringName &enumeration : enumeration_names) {
+ Dictionary values_dict;
+ values_dict["name"] = String(enumeration);
+ values_dict["value"] = Variant::get_enum_value(type, enum_name, enumeration);
+ values.push_back(values_dict);
+ }
+
+ if (values.size()) {
+ enum_dict["values"] = values;
+ }
+ enums.push_back(enum_dict);
+ }
+
+ if (enums.size()) {
+ d["enums"] = enums;
+ }
+ }
+ {
+ //operators
+ Array operators;
+
+ for (int j = 0; j < Variant::VARIANT_MAX; j++) {
+ for (int k = 0; k < Variant::OP_MAX; k++) {
+ Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j));
+ if (rt != Variant::NIL) {
+ Dictionary d2;
+ d2["name"] = Variant::get_operator_name(Variant::Operator(k));
+ if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
+ d2["right_type"] = Variant::get_type_name(Variant::Type(j));
+ }
+ d2["return_type"] = Variant::get_type_name(Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j)));
+ operators.push_back(d2);
+ }
+ }
+ }
+ if (operators.size()) {
+ d["operators"] = operators;
+ }
+ }
+ {
+ //methods
+ Array methods;
+
+ List<StringName> method_names;
+ Variant::get_builtin_method_list(type, &method_names);
+ for (const StringName &method_name : method_names) {
+ Dictionary d2;
+ d2["name"] = String(method_name);
+ if (Variant::has_builtin_method_return_value(type, method_name)) {
+ Variant::Type ret_type = Variant::get_builtin_method_return_type(type, method_name);
+ d2["return_type"] = ret_type == Variant::NIL ? String("Variant") : Variant::get_type_name(ret_type);
+ }
+ d2["is_vararg"] = Variant::is_builtin_method_vararg(type, method_name);
+ d2["is_const"] = Variant::is_builtin_method_const(type, method_name);
+ d2["is_static"] = Variant::is_builtin_method_static(type, method_name);
+ d2["hash"] = Variant::get_builtin_method_hash(type, method_name);
+
+ Vector<Variant> default_args = Variant::get_builtin_method_default_arguments(type, method_name);
+
+ Array arguments;
+ int argcount = Variant::get_builtin_method_argument_count(type, method_name);
+ for (int j = 0; j < argcount; j++) {
+ Dictionary d3;
+ d3["name"] = Variant::get_builtin_method_argument_name(type, method_name, j);
+ Variant::Type argtype = Variant::get_builtin_method_argument_type(type, method_name, j);
+ d3["type"] = argtype == Variant::NIL ? String("Variant") : Variant::get_type_name(argtype);
+
+ if (j >= (argcount - default_args.size())) {
+ int dargidx = j - (argcount - default_args.size());
+ d3["default_value"] = default_args[dargidx].get_construct_string();
+ }
+ arguments.push_back(d3);
+ }
+
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ methods.push_back(d2);
+ }
+ if (methods.size()) {
+ d["methods"] = methods;
+ }
+ }
+ {
+ //constructors
+ Array constructors;
+
+ for (int j = 0; j < Variant::get_constructor_count(type); j++) {
+ Dictionary d2;
+ d2["index"] = j;
+
+ Array arguments;
+ int argcount = Variant::get_constructor_argument_count(type, j);
+ for (int k = 0; k < argcount; k++) {
+ Dictionary d3;
+ d3["name"] = Variant::get_constructor_argument_name(type, j, k);
+ d3["type"] = Variant::get_type_name(Variant::get_constructor_argument_type(type, j, k));
+ arguments.push_back(d3);
+ }
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+ constructors.push_back(d2);
+ }
+
+ if (constructors.size()) {
+ d["constructors"] = constructors;
+ }
+ }
+ {
+ //destructor
+ d["has_destructor"] = Variant::has_destructor(type);
+ }
+
+ builtins.push_back(d);
+ }
+
+ api_dump["builtin_classes"] = builtins;
+ }
+
+ {
+ // classes
+ Array classes;
+
+ List<StringName> class_list;
+
+ ClassDB::get_class_list(&class_list);
+
+ class_list.sort_custom<StringName::AlphCompare>();
+
+ for (const StringName &class_name : class_list) {
+ Dictionary d;
+ d["name"] = String(class_name);
+ d["is_refcounted"] = ClassDB::is_parent_class(class_name, "RefCounted");
+ d["is_instantiable"] = ClassDB::can_instantiate(class_name);
+ StringName parent_class = ClassDB::get_parent_class(class_name);
+ if (parent_class != StringName()) {
+ d["inherits"] = String(parent_class);
+ }
+
+ {
+ ClassDB::APIType api = ClassDB::get_api_type(class_name);
+ static const char *api_type[5] = { "core", "editor", "extension", "editor_extension" };
+ d["api_type"] = api_type[api];
+ }
+
+ {
+ //constants
+ Array constants;
+ List<String> constant_list;
+ ClassDB::get_integer_constant_list(class_name, &constant_list, true);
+ for (const String &F : constant_list) {
+ StringName enum_name = ClassDB::get_integer_constant_enum(class_name, F);
+ if (enum_name != StringName()) {
+ continue; //enums will be handled on their own
+ }
+
+ Dictionary d2;
+ d2["name"] = String(F);
+ d2["value"] = ClassDB::get_integer_constant(class_name, F);
+
+ constants.push_back(d2);
+ }
+
+ if (constants.size()) {
+ d["constants"] = constants;
+ }
+ }
+ {
+ //enum
+ Array enums;
+ List<StringName> enum_list;
+ ClassDB::get_enum_list(class_name, &enum_list, true);
+ for (const StringName &F : enum_list) {
+ Dictionary d2;
+ d2["name"] = String(F);
+ d2["is_bitfield"] = ClassDB::is_enum_bitfield(class_name, F);
+
+ Array values;
+ List<StringName> enum_constant_list;
+ ClassDB::get_enum_constants(class_name, F, &enum_constant_list, true);
+ for (List<StringName>::Element *G = enum_constant_list.front(); G; G = G->next()) {
+ Dictionary d3;
+ d3["name"] = String(G->get());
+ d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
+ values.push_back(d3);
+ }
+
+ d2["values"] = values;
+
+ enums.push_back(d2);
+ }
+
+ if (enums.size()) {
+ d["enums"] = enums;
+ }
+ }
+ {
+ //methods
+ Array methods;
+ List<MethodInfo> method_list;
+ ClassDB::get_method_list(class_name, &method_list, true);
+ for (const MethodInfo &F : method_list) {
+ StringName method_name = F.name;
+ if ((F.flags & METHOD_FLAG_VIRTUAL) && !(F.flags & METHOD_FLAG_OBJECT_CORE)) {
+ //virtual method
+ const MethodInfo &mi = F;
+ Dictionary d2;
+ d2["name"] = String(method_name);
+ d2["is_const"] = (F.flags & METHOD_FLAG_CONST) ? true : false;
+ d2["is_static"] = (F.flags & METHOD_FLAG_STATIC) ? true : false;
+ d2["is_vararg"] = false;
+ d2["is_virtual"] = true;
+ // virtual functions have no hash since no MethodBind is involved
+ bool has_return = mi.return_val.type != Variant::NIL || (mi.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
+ Array arguments;
+ for (int i = (has_return ? -1 : 0); i < mi.arguments.size(); i++) {
+ PropertyInfo pinfo = i == -1 ? mi.return_val : mi.arguments[i];
+ Dictionary d3;
+
+ if (i >= 0) {
+ d3["name"] = pinfo.name;
+ }
+
+ d3["type"] = get_type_name(pinfo);
+
+ if (i == -1) {
+ d2["return_value"] = d3;
+ } else {
+ arguments.push_back(d3);
+ }
+ }
+
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ methods.push_back(d2);
+
+ } else if (F.name.begins_with("_")) {
+ //hidden method, ignore
+
+ } else {
+ Dictionary d2;
+ d2["name"] = String(method_name);
+
+ MethodBind *method = ClassDB::get_method(class_name, method_name);
+ if (!method) {
+ continue;
+ }
+
+ d2["is_const"] = method->is_const();
+ d2["is_vararg"] = method->is_vararg();
+ d2["is_static"] = method->is_static();
+ d2["is_virtual"] = false;
+ d2["hash"] = method->get_hash();
+
+ Vector<Variant> default_args = method->get_default_arguments();
+
+ Array arguments;
+ for (int i = (method->has_return() ? -1 : 0); i < method->get_argument_count(); i++) {
+ PropertyInfo pinfo = i == -1 ? method->get_return_info() : method->get_argument_info(i);
+ Dictionary d3;
+
+ if (i >= 0) {
+ d3["name"] = pinfo.name;
+ }
+ d3["type"] = get_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)];
+ }
+
+ if (i >= 0 && i >= (method->get_argument_count() - default_args.size())) {
+ int dargidx = i - (method->get_argument_count() - default_args.size());
+ d3["default_value"] = default_args[dargidx].get_construct_string();
+ }
+
+ if (i == -1) {
+ d2["return_value"] = d3;
+ } else {
+ arguments.push_back(d3);
+ }
+ }
+
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ methods.push_back(d2);
+ }
+ }
+
+ if (methods.size()) {
+ d["methods"] = methods;
+ }
+ }
+
+ {
+ //signals
+ Array signals;
+ List<MethodInfo> signal_list;
+ ClassDB::get_signal_list(class_name, &signal_list, true);
+ for (const MethodInfo &F : signal_list) {
+ StringName signal_name = F.name;
+ Dictionary d2;
+ d2["name"] = String(signal_name);
+
+ Array arguments;
+
+ for (int i = 0; i < F.arguments.size(); i++) {
+ Dictionary d3;
+ d3["name"] = F.arguments[i].name;
+ d3["type"] = get_type_name(F.arguments[i]);
+ arguments.push_back(d3);
+ }
+ if (arguments.size()) {
+ d2["arguments"] = arguments;
+ }
+
+ signals.push_back(d2);
+ }
+
+ if (signals.size()) {
+ d["signals"] = signals;
+ }
+ }
+ {
+ //properties
+ Array properties;
+ List<PropertyInfo> property_list;
+ ClassDB::get_property_list(class_name, &property_list, true);
+ for (const PropertyInfo &F : property_list) {
+ if (F.usage & PROPERTY_USAGE_CATEGORY || F.usage & PROPERTY_USAGE_GROUP || F.usage & PROPERTY_USAGE_SUBGROUP) {
+ continue; //not real properties
+ }
+ if (F.name.begins_with("_")) {
+ continue; //hidden property
+ }
+ StringName property_name = F.name;
+ Dictionary d2;
+ d2["type"] = get_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);
+ properties.push_back(d2);
+ }
+
+ if (properties.size()) {
+ d["properties"] = properties;
+ }
+ }
+
+ classes.push_back(d);
+ }
+
+ api_dump["classes"] = classes;
+ }
+
+ {
+ // singletons
+
+ Array singletons;
+ List<Engine::Singleton> singleton_list;
+ Engine::get_singleton()->get_singletons(&singleton_list);
+
+ for (const Engine::Singleton &s : singleton_list) {
+ Dictionary d;
+ d["name"] = s.name;
+ if (s.class_name != StringName()) {
+ d["type"] = String(s.class_name);
+ } else {
+ d["type"] = String(s.ptr->get_class());
+ }
+ singletons.push_back(d);
+ }
+
+ if (singletons.size()) {
+ api_dump["singletons"] = singletons;
+ }
+ }
+
+ {
+ Array native_structures;
+
+ List<StringName> native_structs;
+ ClassDB::get_native_struct_list(&native_structs);
+ native_structs.sort_custom<StringName::AlphCompare>();
+
+ for (const StringName &E : native_structs) {
+ String code = ClassDB::get_native_struct_code(E);
+
+ Dictionary d;
+ d["name"] = String(E);
+ d["format"] = code;
+
+ native_structures.push_back(d);
+ }
+
+ api_dump["native_structures"] = native_structures;
+ }
+
+ return api_dump;
+}
+
+void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path) {
+ Dictionary api = generate_extension_api();
+ Ref<JSON> json;
+ json.instantiate();
+
+ String text = json->stringify(api, "\t", false);
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
+ CharString cs = text.ascii();
+ fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
+}
+#endif
diff --git a/core/extension/extension_api_dump.h b/core/extension/extension_api_dump.h
new file mode 100644
index 0000000000..1bc455ea67
--- /dev/null
+++ b/core/extension/extension_api_dump.h
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
+#ifndef EXTENSION_API_DUMP_H
+#define EXTENSION_API_DUMP_H
+
+#include "core/extension/native_extension.h"
+
+#ifdef TOOLS_ENABLED
+
+class NativeExtensionAPIDump {
+public:
+ static Dictionary generate_extension_api();
+ static void generate_extension_json_file(const String &p_path);
+};
+#endif
+
+#endif // EXTENSION_API_DUMP_H
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
new file mode 100644
index 0000000000..ef0b590030
--- /dev/null
+++ b/core/extension/gdnative_interface.cpp
@@ -0,0 +1,1098 @@
+/*************************************************************************/
+/* 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_sub(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst) {
+ const Variant *a = (const Variant *)p_a;
+ const Variant *b = (const Variant *)p_b;
+ memnew_placement(r_dst, Variant);
+ Variant::sub(*a, *b, *(Variant *)r_dst);
+}
+
+static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
+ const Variant *a = (const Variant *)p_a;
+ const Variant *b = (const Variant *)p_b;
+ memnew_placement(r_dst, Variant);
+ Variant::blend(*a, *b, p_c, *(Variant *)r_dst);
+}
+
+static void gdnative_variant_interpolate(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
+ const Variant *a = (const Variant *)p_a;
+ const Variant *b = (const Variant *)p_b;
+ memnew_placement(r_dst, Variant);
+ Variant::interpolate(*a, *b, p_c, *(Variant *)r_dst);
+}
+
+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 (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 (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 (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_ONCE("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_sub = gdnative_variant_sub;
+ gdni.variant_blend = gdnative_variant_blend;
+ gdni.variant_interpolate = gdnative_variant_interpolate;
+ 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
new file mode 100644
index 0000000000..041a6e5112
--- /dev/null
+++ b/core/extension/gdnative_interface.h
@@ -0,0 +1,585 @@
+/*************************************************************************/
+/* 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 {
+ uint32_t type;
+ const char *name;
+ const char *class_name;
+ uint32_t hint;
+ const char *hint_string;
+ uint32_t usage;
+} GDNativePropertyInfo;
+
+typedef struct {
+ const char *name;
+ GDNativePropertyInfo return_value;
+ uint32_t flags; // From 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 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 void (*GDNativeExtensionClassObjectInstance)(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance);
+typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
+
+typedef struct {
+ GDNativeExtensionClassSet set_func;
+ GDNativeExtensionClassGet get_func;
+ GDNativeExtensionClassGetPropertyList get_property_list_func;
+ GDNativeExtensionClassFreePropertyList free_property_list_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; /* 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 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;
+
+ 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_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst);
+ void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
+ void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
+ 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_wrappers.py b/core/extension/make_wrappers.py
new file mode 100644
index 0000000000..862d313fba
--- /dev/null
+++ b/core/extension/make_wrappers.py
@@ -0,0 +1,93 @@
+proto = """
+#define EXBIND$VER($RETTYPE m_name$ARG) \\
+GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\
+virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
+ $RETPRE\\
+ GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\
+ $RETPOST\\
+}
+"""
+
+
+def generate_version(argcount, const=False, returns=False):
+ s = proto
+ sproto = str(argcount)
+ method_info = ""
+ if returns:
+ sproto += "R"
+ s = s.replace("$RETTYPE", "m_ret, ")
+ s = s.replace("$RETVAL", "m_ret")
+ s = s.replace("$RETPRE", "m_ret ret; ZeroInitializer<m_ret>::initialize(ret);\\\n")
+ s = s.replace("$RETPOST", "return ret;\\\n")
+
+ else:
+ s = s.replace("$RETTYPE", "")
+ s = s.replace("$RETVAL", "void")
+ s = s.replace("$RETPRE", "")
+ s = s.replace("$RETPOST", "return;")
+
+ if const:
+ sproto += "C"
+ s = s.replace("$CONST", "const")
+ else:
+ s = s.replace("$CONST", "")
+
+ s = s.replace("$VER", sproto)
+ argtext = ""
+ funcargs = ""
+ callargs = ""
+
+ for i in range(argcount):
+ if i > 0:
+ funcargs += ", "
+
+ argtext += ", m_type" + str(i + 1)
+ funcargs += "m_type" + str(i + 1) + " arg" + str(i + 1)
+ callargs += ", arg" + str(i + 1)
+
+ if argcount:
+ s = s.replace("$ARG", argtext)
+ s = s.replace("$FUNCARGS", funcargs)
+ s = s.replace("$CALLARGS", callargs)
+ else:
+ s = s.replace("$ARG", "")
+ s = s.replace("$FUNCARGS", funcargs)
+ s = s.replace("$CALLARGS", callargs)
+
+ if returns:
+ s = s.replace("$RETREF", ", ret")
+ else:
+ s = s.replace("$RETREF", "")
+
+ return s
+
+
+def run(target, source, env):
+
+ max_versions = 12
+
+ txt = """
+#ifndef GDEXTENSION_WRAPPERS_GEN_H
+#define GDEXTENSION_WRAPPERS_GEN_H
+
+
+"""
+
+ for i in range(max_versions + 1):
+
+ txt += "/* " + str(i) + " Arguments */\n\n"
+ txt += generate_version(i, False, False)
+ txt += generate_version(i, False, True)
+ txt += generate_version(i, True, False)
+ txt += generate_version(i, True, True)
+
+ txt += "#endif"
+
+ with open(target[0], "w") as f:
+ f.write(txt)
+
+
+if __name__ == "__main__":
+ from platform_methods import subprocess_main
+
+ subprocess_main(globals())
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
new file mode 100644
index 0000000000..b69859b441
--- /dev/null
+++ b/core/extension/native_extension.cpp
@@ -0,0 +1,455 @@
+/*************************************************************************/
+/* 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().plus_file("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.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.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 config 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 config file must contain '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;
+ }
+ ERR_PRINT("No GDExtension library found for current architecture; in config file " + p_path);
+ return Ref<Resource>();
+ }
+
+ if (!library_path.is_resource_file() && !library_path.is_absolute_path()) {
+ library_path = p_path.get_base_dir().plus_file(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
new file mode 100644
index 0000000000..b7238d2899
--- /dev/null
+++ b/core/extension/native_extension.h
@@ -0,0 +1,100 @@
+/*************************************************************************/
+/* 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
new file mode 100644
index 0000000000..186fcc44f6
--- /dev/null
+++ b/core/extension/native_extension_manager.cpp
@@ -0,0 +1,149 @@
+/*************************************************************************/
+/* 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;
+}
diff --git a/core/extension/native_extension_manager.h b/core/extension/native_extension_manager.h
new file mode 100644
index 0000000000..ed80cd6b7a
--- /dev/null
+++ b/core/extension/native_extension_manager.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* 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. */
+/*************************************************************************/
+
+#ifndef NATIVE_EXTENSION_MANAGER_H
+#define NATIVE_EXTENSION_MANAGER_H
+
+#include "core/extension/native_extension.h"
+
+class NativeExtensionManager : public Object {
+ GDCLASS(NativeExtensionManager, Object);
+
+ int32_t level = -1;
+ HashMap<String, Ref<NativeExtension>> native_extension_map;
+
+ static void _bind_methods();
+
+ static NativeExtensionManager *singleton;
+
+public:
+ enum LoadStatus {
+ LOAD_STATUS_OK,
+ LOAD_STATUS_FAILED,
+ LOAD_STATUS_ALREADY_LOADED,
+ LOAD_STATUS_NOT_LOADED,
+ LOAD_STATUS_NEEDS_RESTART,
+ };
+
+ LoadStatus load_extension(const String &p_path);
+ LoadStatus reload_extension(const String &p_path);
+ 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);
+
+ void initialize_extensions(NativeExtension::InitializationLevel p_level);
+ void deinitialize_extensions(NativeExtension::InitializationLevel p_level);
+
+ static NativeExtensionManager *get_singleton();
+
+ void load_extensions();
+
+ NativeExtensionManager();
+};
+
+VARIANT_ENUM_CAST(NativeExtensionManager::LoadStatus)
+
+#endif // NATIVE_EXTENSION_MANAGER_H