Просмотр исходного кода

Merge pull request #663 from groud/move_godot_object_init_to_extension

Rémi Verschelde 3 лет назад
Родитель
Сommit
f58a2f25a2

+ 1 - 0
SConstruct

@@ -458,6 +458,7 @@ if should_generate_bindings:
 # Sources to compile
 sources = []
 add_sources(sources, "src", "cpp")
+add_sources(sources, "src/classes", "cpp")
 add_sources(sources, "src/core", "cpp")
 add_sources(sources, "src/variant", "cpp")
 add_sources(sources, "gen/src/variant", "cpp")

+ 0 - 3
binding_generator.py

@@ -914,9 +914,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
     result.append("")
 
     result.append("public:")
-
-    # Constructor override, since parent Wrapped has protected constructor.
-    result.append(f"\t{class_name}() = default;")
     result.append("")
 
     if "enums" in class_api:

+ 1 - 1
godot-headers

@@ -1 +1 @@
-Subproject commit cfc1909edf55f21a8822dd088172dcf6c349a1d0
+Subproject commit 68e989fce33a14fdd9e10c8adc88ae3c9b3aae85

+ 128 - 151
include/godot_cpp/classes/wrapped.hpp

@@ -34,6 +34,7 @@
 #include <godot_cpp/core/memory.hpp>
 
 #include <godot_cpp/godot.hpp>
+
 namespace godot {
 
 typedef void GodotObject;
@@ -41,46 +42,22 @@ typedef void GodotObject;
 // Base for all engine classes, to contain the pointer to the engine instance.
 class Wrapped {
 	friend class GDExtensionBinding;
-
-	// Private constructor, this should not be created directly by users.
-	Wrapped(GodotObject *p_owner) :
-			_owner(p_owner) {}
+	friend void postinitialize_handler(Wrapped *);
 
 protected:
-	Wrapped() = default;
+	virtual const char *_get_class() const = 0; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
+	virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const = 0;
+
+	void _postinitialize();
+
+	Wrapped(const char *p_godot_class);
+	Wrapped(GodotObject *p_godot_object);
 
 public:
 	// Must be public but you should not touch this.
 	GodotObject *_owner = nullptr;
-
-	static Wrapped *_new() {
-		return nullptr;
-	}
 };
 
-namespace internal {
-
-template <class T, class Enable = void>
-struct Creator {
-	static T *_new() { return nullptr; }
-};
-
-template <class T>
-struct Creator<T, typename std::enable_if<std::is_base_of_v<godot::Wrapped, T>>::type> {
-	static T *_new() { return T::_new(); }
-};
-
-// template <class T>
-// struct Creator<T, std::false_type> {
-// };
-
-// template <class T>
-// struct Creator<T, std::enable_if_t<std::is_base_of_v<godot::Wrapped, T>, bool>> {
-// 	static T *_new() { return T::_new(); }
-// };
-
-}; // namespace internal
-
 } // namespace godot
 
 #ifdef DEBUG_ENABLED
@@ -94,126 +71,126 @@ struct Creator<T, typename std::enable_if<std::is_base_of_v<godot::Wrapped, T>>:
 #define CHECK_CLASS_CONSTRUCTOR(m_constructor, m_class)
 #endif
 
-#define GDCLASS(m_class, m_inherits)                                                                                                                                  \
-private:                                                                                                                                                              \
-	friend class ClassDB;                                                                                                                                             \
-                                                                                                                                                                      \
-	using SelfType = m_class;                                                                                                                                         \
-                                                                                                                                                                      \
-protected:                                                                                                                                                            \
-	static void (*_get_bind_methods())() {                                                                                                                            \
-		return &m_class::_bind_methods;                                                                                                                               \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	template <class T>                                                                                                                                                \
-	static void register_virtuals() {                                                                                                                                 \
-		m_inherits::register_virtuals<T>();                                                                                                                           \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-public:                                                                                                                                                               \
-	static void initialize_class() {                                                                                                                                  \
-		static bool initialized = false;                                                                                                                              \
-		if (initialized) {                                                                                                                                            \
-			return;                                                                                                                                                   \
-		}                                                                                                                                                             \
-		m_inherits::initialize_class();                                                                                                                               \
-		if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) {                                                                                        \
-			_bind_methods();                                                                                                                                          \
-			m_inherits::register_virtuals<m_class>();                                                                                                                 \
-		}                                                                                                                                                             \
-		initialized = true;                                                                                                                                           \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static const char *get_class_static() {                                                                                                                           \
-		return #m_class;                                                                                                                                              \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static const char *get_parent_class_static() {                                                                                                                    \
-		return #m_inherits;                                                                                                                                           \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static GDExtensionClassInstancePtr create(void *data) {                                                                                                           \
-		return reinterpret_cast<GDExtensionClassInstancePtr>(new ("") m_class);                                                                                       \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static void free(void *data, GDExtensionClassInstancePtr ptr) {                                                                                                   \
-		if (ptr) {                                                                                                                                                    \
-			m_class *cls = reinterpret_cast<m_class *>(ptr);                                                                                                          \
-			cls->~m_class();                                                                                                                                          \
-			::godot::Memory::free_static(cls);                                                                                                                        \
-		}                                                                                                                                                             \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static void set_object_instance(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance) {                                                    \
-		godot::internal::gdn_interface->object_set_instance_binding(p_object_instance, godot::internal::token, p_instance, &m_class::___binding_callbacks);           \
-		reinterpret_cast<m_class *>(p_instance)->_owner = reinterpret_cast<godot::GodotObject *>(p_object_instance);                                                  \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static void *___binding_create_callback(void *p_token, void *p_instance) {                                                                                        \
-		return nullptr;                                                                                                                                               \
-	}                                                                                                                                                                 \
-	static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) {                                                                          \
-	}                                                                                                                                                                 \
-	static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) {                                                    \
-		return true;                                                                                                                                                  \
-	}                                                                                                                                                                 \
-	static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = {                                                                                        \
-		___binding_create_callback,                                                                                                                                   \
-		___binding_free_callback,                                                                                                                                     \
-		___binding_reference_callback,                                                                                                                                \
-	};                                                                                                                                                                \
-                                                                                                                                                                      \
-	static m_class *_new() {                                                                                                                                          \
-		static GDNativeExtensionPtr ___extension = nullptr;                                                                                                           \
-		static GDNativeClassConstructor ___constructor = godot::internal::gdn_interface->classdb_get_constructor(#m_class, &___extension);                            \
-		CHECK_CLASS_CONSTRUCTOR(___constructor, m_class);                                                                                                             \
-		GDNativeObjectPtr obj = godot::internal::gdn_interface->classdb_construct_object(___constructor, ___extension);                                               \
-		return reinterpret_cast<m_class *>(godot::internal::gdn_interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-private:
+#define GDCLASS(m_class, m_inherits)                                                                               \
+private:                                                                                                           \
+	void operator=(const m_class &p_rval) {}                                                                       \
+	friend class ClassDB;                                                                                          \
+                                                                                                                   \
+	using SelfType = m_class;                                                                                      \
+                                                                                                                   \
+protected:                                                                                                         \
+	virtual const char *_get_class() const override {                                                              \
+		return get_class_static();                                                                                 \
+	}                                                                                                              \
+                                                                                                                   \
+	virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override {                     \
+		return &___binding_callbacks;                                                                              \
+	}                                                                                                              \
+                                                                                                                   \
+	static void (*_get_bind_methods())() {                                                                         \
+		return &m_class::_bind_methods;                                                                            \
+	}                                                                                                              \
+                                                                                                                   \
+	template <class T>                                                                                             \
+	static void register_virtuals() {                                                                              \
+		m_inherits::register_virtuals<T>();                                                                        \
+	}                                                                                                              \
+                                                                                                                   \
+public:                                                                                                            \
+	static void initialize_class() {                                                                               \
+		static bool initialized = false;                                                                           \
+		if (initialized) {                                                                                         \
+			return;                                                                                                \
+		}                                                                                                          \
+		m_inherits::initialize_class();                                                                            \
+		if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) {                                     \
+			_bind_methods();                                                                                       \
+			m_inherits::register_virtuals<m_class>();                                                              \
+		}                                                                                                          \
+		initialized = true;                                                                                        \
+	}                                                                                                              \
+                                                                                                                   \
+	static const char *get_class_static() {                                                                        \
+		return #m_class;                                                                                           \
+	}                                                                                                              \
+                                                                                                                   \
+	static const char *get_parent_class_static() {                                                                 \
+		return #m_inherits;                                                                                        \
+	}                                                                                                              \
+                                                                                                                   \
+	static GDNativeObjectPtr create(void *data) {                                                                  \
+		m_class *new_object = memnew(m_class);                                                                     \
+		return new_object->_owner;                                                                                 \
+	}                                                                                                              \
+                                                                                                                   \
+	static void free(void *data, GDExtensionClassInstancePtr ptr) {                                                \
+		if (ptr) {                                                                                                 \
+			m_class *cls = reinterpret_cast<m_class *>(ptr);                                                       \
+			cls->~m_class();                                                                                       \
+			::godot::Memory::free_static(cls);                                                                     \
+		}                                                                                                          \
+	}                                                                                                              \
+                                                                                                                   \
+	static void *___binding_create_callback(void *p_token, void *p_instance) {                                     \
+		return nullptr;                                                                                            \
+	}                                                                                                              \
+	static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) {                       \
+	}                                                                                                              \
+	static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \
+		return true;                                                                                               \
+	}                                                                                                              \
+	static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = {                                     \
+		___binding_create_callback,                                                                                \
+		___binding_free_callback,                                                                                  \
+		___binding_reference_callback,                                                                             \
+	};
 
 // Don't use this for your classes, use GDCLASS() instead.
-#define GDNATIVE_CLASS(m_class, m_inherits)                                                                                                                           \
-protected:                                                                                                                                                            \
-	static void (*_get_bind_methods())() {                                                                                                                            \
-		return nullptr;                                                                                                                                               \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-public:                                                                                                                                                               \
-	static void initialize_class() {}                                                                                                                                 \
-                                                                                                                                                                      \
-	static const char *get_class_static() {                                                                                                                           \
-		return #m_class;                                                                                                                                              \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static const char *get_parent_class_static() {                                                                                                                    \
-		return #m_inherits;                                                                                                                                           \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-	static void *___binding_create_callback(void *p_token, void *p_instance) {                                                                                        \
-		m_class *obj = new ("") m_class;                                                                                                                              \
-		obj->_owner = (godot::GodotObject *)p_instance;                                                                                                               \
-		return obj;                                                                                                                                                   \
-	}                                                                                                                                                                 \
-	static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) {                                                                          \
-		Memory::free_static(reinterpret_cast<m_class *>(p_binding));                                                                                                  \
-	}                                                                                                                                                                 \
-	static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) {                                                    \
-		return true;                                                                                                                                                  \
-	}                                                                                                                                                                 \
-	static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = {                                                                                        \
-		___binding_create_callback,                                                                                                                                   \
-		___binding_free_callback,                                                                                                                                     \
-		___binding_reference_callback,                                                                                                                                \
-	};                                                                                                                                                                \
-	static m_class *_new() {                                                                                                                                          \
-		static GDNativeClassConstructor ___constructor = godot::internal::gdn_interface->classdb_get_constructor(#m_class, nullptr);                                  \
-		CHECK_CLASS_CONSTRUCTOR(___constructor, m_class);                                                                                                             \
-		GDNativeObjectPtr obj = ___constructor();                                                                                                                     \
-		return reinterpret_cast<m_class *>(godot::internal::gdn_interface->object_get_instance_binding(obj, godot::internal::token, &m_class::___binding_callbacks)); \
-	}                                                                                                                                                                 \
-                                                                                                                                                                      \
-private:
+#define GDNATIVE_CLASS(m_class, m_inherits)                                                                        \
+private:                                                                                                           \
+	void operator=(const m_class &p_rval) {}                                                                       \
+                                                                                                                   \
+protected:                                                                                                         \
+	virtual const char *_get_class() const override {                                                              \
+		return get_class_static();                                                                                 \
+	}                                                                                                              \
+                                                                                                                   \
+	virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override {                     \
+		return &___binding_callbacks;                                                                              \
+	}                                                                                                              \
+                                                                                                                   \
+	m_class(const char *p_godot_class) : m_inherits(p_godot_class) {}                                              \
+	m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {}                                           \
+                                                                                                                   \
+	static void (*_get_bind_methods())() {                                                                         \
+		return nullptr;                                                                                            \
+	}                                                                                                              \
+                                                                                                                   \
+public:                                                                                                            \
+	static void initialize_class() {}                                                                              \
+                                                                                                                   \
+	static const char *get_class_static() {                                                                        \
+		return #m_class;                                                                                           \
+	}                                                                                                              \
+                                                                                                                   \
+	static const char *get_parent_class_static() {                                                                 \
+		return #m_inherits;                                                                                        \
+	}                                                                                                              \
+                                                                                                                   \
+	static void *___binding_create_callback(void *p_token, void *p_instance) {                                     \
+		return memnew(m_class((GodotObject *)p_instance));                                                         \
+	}                                                                                                              \
+	static void ___binding_free_callback(void *p_token, void *p_instance, void *p_binding) {                       \
+		Memory::free_static(reinterpret_cast<m_class *>(p_binding));                                               \
+	}                                                                                                              \
+	static GDNativeBool ___binding_reference_callback(void *p_token, void *p_instance, GDNativeBool p_reference) { \
+		return true;                                                                                               \
+	}                                                                                                              \
+	static constexpr GDNativeInstanceBindingCallbacks ___binding_callbacks = {                                     \
+		___binding_create_callback,                                                                                \
+		___binding_free_callback,                                                                                  \
+		___binding_reference_callback,                                                                             \
+	};                                                                                                             \
+	m_class() : m_class(#m_class) {}
 
 #endif // ! GODOT_CPP_WRAPPED_HPP

+ 1 - 2
include/godot_cpp/core/class_db.hpp

@@ -158,9 +158,8 @@ void ClassDB::register_class() {
 		nullptr, // GDNativeExtensionClassUnreference
 		T::create, // GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
 		T::free, // GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
-		T::set_object_instance, // GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */
 		&ClassDB::get_virtual_func, // GDNativeExtensionClassGetVirtual get_virtual_func;
-		(void *)cl.name, //void *class_userdata;
+		(void *)cl.name, // void *class_userdata;
 	};
 
 	internal::gdn_interface->classdb_register_extension_class(internal::library, cl.name, cl.parent_name, &class_info);

+ 11 - 10
include/godot_cpp/core/memory.hpp

@@ -68,16 +68,17 @@ public:
 	static void free_static(void *p_ptr);
 };
 
-#define memnew(m_v)                                                           \
-	([&]() {                                                                  \
-		if constexpr (std::is_base_of<godot::Object, decltype(m_v)>::value) { \
-			return godot::internal::Creator<decltype(m_v)>::_new();           \
-		} else {                                                              \
-			return new ("") m_v;                                              \
-		}                                                                     \
-	}())
-
-#define memnew_placement(m_placement, m_class) (new (m_placement, sizeof(m_class), "") m_class)
+_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
+
+template <class T>
+_ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
+	postinitialize_handler(p_obj);
+	return p_obj;
+}
+
+#define memnew(m_class) _post_initialize(new ("") m_class)
+
+#define memnew_placement(m_placement, m_class) _post_initialize(new (m_placement, sizeof(m_class), "") m_class)
 
 template <class T>
 void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = 0) {

+ 0 - 3
include/godot_cpp/godot.hpp

@@ -55,9 +55,6 @@ public:
 	static void initialize_level(void *userdata, GDNativeInitializationLevel p_level);
 	static void deinitialize_level(void *userdata, GDNativeInitializationLevel p_level);
 
-	static void *create_instance_callback(void *p_token, void *p_instance);
-	static void free_instance_callback(void *p_token, void *p_instance, void *p_binding);
-
 	class InitObject {
 		const GDNativeInterface *gdn_interface;
 		const GDNativeExtensionClassLibraryPtr library;

+ 56 - 0
src/classes/wrapped.cpp

@@ -0,0 +1,56 @@
+/*************************************************************************/
+/*  wrapped.cpp                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 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 <godot_cpp/classes/wrapped.hpp>
+
+#include <godot_cpp/variant/builtin_types.hpp>
+
+#include <godot_cpp/classes/object.hpp>
+
+namespace godot {
+
+void Wrapped::_postinitialize() {
+	godot::internal::gdn_interface->object_set_instance(_owner, _get_class(), this);
+	godot::internal::gdn_interface->object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks());
+}
+
+Wrapped::Wrapped(const char *p_godot_class) {
+	_owner = godot::internal::gdn_interface->classdb_construct_object(p_godot_class);
+}
+
+Wrapped::Wrapped(GodotObject *p_godot_object) {
+	_owner = p_godot_object;
+}
+
+void postinitialize_handler(Wrapped *p_wrapped) {
+	p_wrapped->_postinitialize();
+}
+
+} // namespace godot

+ 0 - 11
src/godot.cpp

@@ -91,17 +91,6 @@ void GDExtensionBinding::deinitialize_level(void *userdata, GDNativeInitializati
 	}
 }
 
-void *GDExtensionBinding::create_instance_callback(void *p_token, void *p_instance) {
-	ERR_FAIL_COND_V_MSG(p_token != internal::library, nullptr, "Asking for creating instance with invalid token.");
-	Wrapped *wrapped = memnew(Wrapped(p_instance));
-	return wrapped;
-}
-
-void GDExtensionBinding::free_instance_callback(void *p_token, void *p_instance, void *p_binding) {
-	ERR_FAIL_COND_MSG(p_token != internal::library, "Asking for freeing instance with invalid token.");
-	memdelete((Wrapped *)p_binding);
-}
-
 void GDExtensionBinding::InitObject::register_core_initializer(Callback p_core_init) const {
 	GDExtensionBinding::init_callbacks[GDNATIVE_INITIALIZATION_CORE] = p_core_init;
 }