Merge pull request #113282 from dsnopek/required-ptr-get-out-there

Use `RequiredParam`/`RequiredResult` in some high value places
This commit is contained in:
Thaddeus Crews 2025-12-02 20:42:53 -06:00
commit 9f76aa3df5
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
79 changed files with 372 additions and 321 deletions

View file

@ -670,9 +670,9 @@ void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), co
r_error.error = Callable::CallError::CALL_OK;
#ifdef DEBUG_ENABLED
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
r_ret = VariantInternal::make((p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...));
#else
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
r_ret = VariantInternal::make((p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...));
#endif
}
@ -681,9 +681,9 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
r_error.error = Callable::CallError::CALL_OK;
#ifdef DEBUG_ENABLED
r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
r_ret = VariantInternal::make((p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...));
#else
r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
r_ret = VariantInternal::make((p_method)(VariantCaster<P>::cast(*p_args[Is])...));
#endif // DEBUG_ENABLED
}
@ -721,9 +721,9 @@ void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) co
r_error.error = Callable::CallError::CALL_OK;
#ifdef DEBUG_ENABLED
r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
r_ret = VariantInternal::make((p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...));
#else
r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...);
r_ret = VariantInternal::make((p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...));
#endif // DEBUG_ENABLED
(void)p_args;
}
@ -787,9 +787,9 @@ void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *,
r_error.error = Callable::CallError::CALL_OK;
#ifdef DEBUG_ENABLED
r_ret = (p_method)(p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
r_ret = VariantInternal::make((p_method)(p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...));
#else
r_ret = (p_method)(p_instance, VariantCaster<P>::cast(*p_args[Is])...);
r_ret = VariantInternal::make((p_method)(p_instance, VariantCaster<P>::cast(*p_args[Is])...));
#endif // DEBUG_ENABLED
(void)p_args;

View file

@ -253,8 +253,8 @@ struct PtrToArg<T *> {
return likely(p_ptr) ? *reinterpret_cast<T *const *>(p_ptr) : nullptr;
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*((T **)p_ptr) = p_var;
_FORCE_INLINE_ static void encode(const T *p_var, void *p_ptr) {
*((T **)p_ptr) = const_cast<T *>(p_var);
}
};
@ -264,8 +264,8 @@ struct PtrToArg<const T *> {
return likely(p_ptr) ? *reinterpret_cast<T *const *>(p_ptr) : nullptr;
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
*((T **)p_ptr) = p_var;
_FORCE_INLINE_ static void encode(const T *p_var, void *p_ptr) {
*((T **)p_ptr) = const_cast<T *>(p_var);
}
};

View file

@ -32,6 +32,9 @@
#include "core/variant/variant.h"
// Using `RequiredResult<T>` as the return type indicates that null will only be returned in the case of an error.
// This allows GDExtension language bindings to use the appropriate error handling mechanism for that language
// when null is returned (for example, throwing an exception), rather than simply returning the value.
template <typename T>
class RequiredResult {
static_assert(!is_fully_defined_v<T> || std::is_base_of_v<Object, T>, "T must be an Object subtype");
@ -43,9 +46,9 @@ public:
private:
ptr_type _value = ptr_type();
public:
_FORCE_INLINE_ RequiredResult() = default;
public:
RequiredResult(const RequiredResult &p_other) = default;
RequiredResult(RequiredResult &&p_other) = default;
RequiredResult &operator=(const RequiredResult &p_other) = default;
@ -123,12 +126,13 @@ public:
return _value;
}
_FORCE_INLINE_ operator ptr_type() {
_FORCE_INLINE_ operator ptr_type() const {
return _value;
}
_FORCE_INLINE_ operator Variant() const {
return Variant(_value);
template <typename T_Other, std::enable_if_t<std::is_base_of_v<RefCounted, T> && std::is_base_of_v<T, T_Other>, int> = 0>
_FORCE_INLINE_ operator Ref<T_Other>() const {
return Ref<T_Other>(_value);
}
_FORCE_INLINE_ element_type *operator*() const {
@ -140,6 +144,10 @@ public:
}
};
// Using `RequiredParam<T>` as an argument type indicates that passing null as that parameter is an error,
// that will prevent the method from doing its intended function.
// This allows GDExtension bindings to use language-specific mechanisms to prevent users from passing null,
// because it is never valid to do so.
template <typename T>
class RequiredParam {
static_assert(!is_fully_defined_v<T> || std::is_base_of_v<Object, T>, "T must be an Object subtype");

View file

@ -40,6 +40,12 @@
class RefCounted;
template <typename T>
struct GDExtensionConstPtr;
template <typename T>
struct GDExtensionPtr;
class VariantInternal {
friend class Variant;
@ -539,6 +545,29 @@ public:
}
ERR_FAIL_V(nullptr);
}
// Used internally in GDExtension and Godot's binding system when converting to Variant
// from values that may include RequiredParam<T> or RequiredResult<T>.
template <typename T>
_FORCE_INLINE_ static Variant make(const T &v) {
return Variant(v);
}
template <typename T>
_FORCE_INLINE_ static Variant make(const GDExtensionConstPtr<T> &v) {
return v.operator Variant();
}
template <typename T>
_FORCE_INLINE_ static Variant make(const GDExtensionPtr<T> &v) {
return v.operator Variant();
}
template <typename T>
_FORCE_INLINE_ static Variant make(const RequiredParam<T> &v) {
return Variant(v._internal_ptr_dont_use());
}
template <typename T>
_FORCE_INLINE_ static Variant make(const RequiredResult<T> &v) {
return Variant(v._internal_ptr_dont_use());
}
};
template <typename T, typename = void>