Ensure GDExtension class is the correct type for the Godot engine class

This commit is contained in:
David Snopek
2023-02-17 10:49:09 -06:00
parent 1c18413de0
commit 431e30bc32
12 changed files with 124 additions and 18 deletions

View File

@@ -242,9 +242,7 @@ struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
// Important: p_ptr is T*, not Ref<T>*, since Object* is what engine gives to ptrcall.
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
return Ref<T>(reinterpret_cast<T *>(godot::internal::gdextension_interface_object_get_instance_binding(
reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)),
godot::internal::token, &T::___binding_callbacks)));
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)))));
}
typedef Ref<T> EncodeT;
@@ -267,9 +265,7 @@ struct PtrToArg<const Ref<T> &> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
return Ref<T>(reinterpret_cast<T *>(godot::internal::gdextension_interface_object_get_instance_binding(
reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)),
godot::internal::token, &T::___binding_callbacks)));
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)))));
}
};

View File

@@ -104,6 +104,7 @@ public:
private:
// This may only contain custom classes, not Godot classes
static std::unordered_map<StringName, ClassInfo> classes;
static std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *> instance_binding_callbacks;
static MethodBind *bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const void **p_defs, int p_defcount);
static void initialize_class(const ClassInfo &cl);
@@ -117,6 +118,8 @@ public:
static void register_class(bool p_virtual = false);
template <class T>
static void register_abstract_class();
template <class T>
static void register_engine_class();
template <class N, class M, typename... VarArgs>
static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
@@ -137,6 +140,7 @@ public:
static MethodBind *get_method(const StringName &p_class, const StringName &p_method);
static GDExtensionClassCallVirtual get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name);
static const GDExtensionInstanceBindingCallbacks *get_instance_binding_callbacks(const StringName &p_class);
static void initialize(GDExtensionInitializationLevel p_level);
static void deinitialize(GDExtensionInitializationLevel p_level);
@@ -161,6 +165,8 @@ public:
template <class T, bool is_abstract>
void ClassDB::_register_class(bool p_virtual) {
instance_binding_callbacks[T::get_class_static()] = &T::___binding_callbacks;
// Register this class within our plugin
ClassInfo cl;
cl.name = T::get_class_static();
@@ -213,6 +219,11 @@ void ClassDB::register_abstract_class() {
ClassDB::_register_class<T, true>();
}
template <class T>
void ClassDB::register_engine_class() {
instance_binding_callbacks[T::get_class_static()] = &T::___binding_callbacks;
}
template <class N, class M, typename... VarArgs>
MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.

View File

@@ -51,7 +51,7 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co
if (ret == nullptr) {
return nullptr;
}
return reinterpret_cast<O *>(internal::gdextension_interface_object_get_instance_binding(ret, internal::token, &O::___binding_callbacks));
return reinterpret_cast<O *>(internal::get_object_instance_binding(ret));
}
template <class R, class... Args>
@@ -81,7 +81,7 @@ Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, void *in
GodotObject *ret = nullptr;
std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
func(&ret, mb_args.data(), mb_args.size());
return (Object *)internal::gdextension_interface_object_get_instance_binding(ret, internal::token, &Object::___binding_callbacks);
return (Object *)internal::get_object_instance_binding(ret);
}
template <class... Args>

View File

@@ -33,6 +33,7 @@
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/godot.hpp>
#include <godot_cpp/variant/variant.hpp>
@@ -168,9 +169,7 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
template <class T>
struct PtrToArg<T *> {
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::gdextension_interface_object_get_instance_binding(
reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)),
godot::internal::token, &T::___binding_callbacks));
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr))));
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
@@ -181,9 +180,7 @@ struct PtrToArg<T *> {
template <class T>
struct PtrToArg<const T *> {
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::gdextension_interface_object_get_instance_binding(
reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)),
godot::internal::token, &T::___binding_callbacks));
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr))));
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {

View File

@@ -52,6 +52,12 @@
namespace godot {
namespace internal {
Object *get_object_instance_binding(GodotObject *);
} // namespace internal
struct MethodInfo {
StringName name;
PropertyInfo return_val;
@@ -128,7 +134,7 @@ public:
if (obj == nullptr) {
return nullptr;
}
return reinterpret_cast<Object *>(internal::gdextension_interface_object_get_instance_binding(obj, internal::token, &Object::___binding_callbacks));
return internal::get_object_instance_binding(obj);
}
};
@@ -142,7 +148,7 @@ T *Object::cast_to(Object *p_object) {
if (casted == nullptr) {
return nullptr;
}
return reinterpret_cast<T *>(internal::gdextension_interface_object_get_instance_binding(casted, internal::token, &T::___binding_callbacks));
return dynamic_cast<T *>(internal::get_object_instance_binding(casted));
}
template <class T>
@@ -155,7 +161,7 @@ const T *Object::cast_to(const Object *p_object) {
if (casted == nullptr) {
return nullptr;
}
return reinterpret_cast<const T *>(internal::gdextension_interface_object_get_instance_binding(casted, internal::token, &T::___binding_callbacks));
return dynamic_cast<const T *>(internal::get_object_instance_binding(casted));
}
} // namespace godot

View File

@@ -159,6 +159,7 @@ extern "C" GDExtensionInterfaceGlobalGetSingleton gdextension_interface_global_g
extern "C" GDExtensionInterfaceObjectGetInstanceBinding gdextension_interface_object_get_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstanceBinding gdextension_interface_object_set_instance_binding;
extern "C" GDExtensionInterfaceObjectSetInstance gdextension_interface_object_set_instance;
extern "C" GDExtensionInterfaceObjectGetClassName gdextension_interface_object_get_class_name;
extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to;
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
@@ -188,6 +189,9 @@ enum ModuleInitializationLevel {
};
class GDExtensionBinding {
private:
static void register_engine_classes();
public:
using Callback = void (*)(ModuleInitializationLevel p_level);