Compare commits

..

2 Commits

Author SHA1 Message Date
David Snopek e9d1f8b134
Merge 566742d057 into 36847f6af0 2024-02-01 19:48:51 +00:00
David Snopek 566742d057 Avoid creating objects that Godot is going to use placement new to initialize 2024-02-01 13:46:02 -06:00
2 changed files with 33 additions and 24 deletions

View File

@ -190,15 +190,24 @@ struct _GlobalNilClass {
static _GlobalNil _nil; static _GlobalNil _nil;
}; };
// This is for allocating uninitialized memory for passing to GDExtension functions that
// will use placement new to construct a new object.
//
// NOTE: You MUST make sure that the value is initialized before the object goes out of
// scope, otherwise the destructor will be run on junk memory and "bad things" will happen.
template <class T, size_t Alignment = alignof(T)> template <class T, size_t Alignment = alignof(T)>
class UninitializedValue { class ManuallyInitializedValue {
typename std::aligned_storage<sizeof(T), Alignment>::type data; typename std::aligned_storage<sizeof(T), Alignment>::type data;
public: public:
UninitializedValue() {} ManuallyInitializedValue() {}
UninitializedValue(const UninitializedValue &) = delete; ManuallyInitializedValue(const ManuallyInitializedValue &) = delete;
UninitializedValue &operator=(const UninitializedValue &) = delete; ManuallyInitializedValue &operator=(const ManuallyInitializedValue &) = delete;
~ManuallyInitializedValue() {
reinterpret_cast<T *>(&data)->~T();
}
T &get() { T &get() {
return *reinterpret_cast<T *>(&data); return *reinterpret_cast<T *>(&data);

View File

@ -303,9 +303,9 @@ Variant::operator float() const {
} }
Variant::operator String() const { Variant::operator String() const {
String result; ManuallyInitializedValue<String> result;
to_type_constructor[STRING](result._native_ptr(), _native_ptr()); to_type_constructor[STRING](result.ptr(), _native_ptr());
return result; return result.get();
} }
Variant::operator Vector2() const { Variant::operator Vector2() const {
@ -405,9 +405,9 @@ Variant::operator Color() const {
} }
Variant::operator StringName() const { Variant::operator StringName() const {
StringName result; ManuallyInitializedValue<StringName> result;
to_type_constructor[STRING_NAME](result._native_ptr(), _native_ptr()); to_type_constructor[STRING_NAME](result.ptr(), _native_ptr());
return result; return result.get();
} }
Variant::operator NodePath() const { Variant::operator NodePath() const {
@ -459,13 +459,13 @@ Variant::operator Signal() const {
} }
Variant::operator Dictionary() const { Variant::operator Dictionary() const {
UninitializedValue<Dictionary> result; ManuallyInitializedValue<Dictionary> result;
to_type_constructor[DICTIONARY](result.ptr(), _native_ptr()); to_type_constructor[DICTIONARY](result.ptr(), _native_ptr());
return result.get(); return result.get();
} }
Variant::operator Array() const { Variant::operator Array() const {
UninitializedValue<Array> result; ManuallyInitializedValue<Array> result;
to_type_constructor[ARRAY](result.ptr(), _native_ptr()); to_type_constructor[ARRAY](result.ptr(), _native_ptr());
return result.get(); return result.get();
} }
@ -607,39 +607,39 @@ void Variant::set_keyed(const Variant &key, const Variant &value, bool &r_valid)
} }
Variant Variant::get(const Variant &key, bool *r_valid) const { Variant Variant::get(const Variant &key, bool *r_valid) const {
Variant result; ManuallyInitializedValue<Variant> result;
GDExtensionBool valid; GDExtensionBool valid;
internal::gdextension_interface_variant_get(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid); internal::gdextension_interface_variant_get(_native_ptr(), key._native_ptr(), result.ptr(), &valid);
if (r_valid) { if (r_valid) {
*r_valid = PtrToArg<bool>::convert(&valid); *r_valid = PtrToArg<bool>::convert(&valid);
} }
return result; return result.get();
} }
Variant Variant::get_named(const StringName &name, bool &r_valid) const { Variant Variant::get_named(const StringName &name, bool &r_valid) const {
Variant result; ManuallyInitializedValue<Variant> result;
GDExtensionBool valid; GDExtensionBool valid;
internal::gdextension_interface_variant_get_named(_native_ptr(), name._native_ptr(), result._native_ptr(), &valid); internal::gdextension_interface_variant_get_named(_native_ptr(), name._native_ptr(), result.ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid); r_valid = PtrToArg<bool>::convert(&valid);
return result; return result.get();
} }
Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const { Variant Variant::get_indexed(int64_t index, bool &r_valid, bool &r_oob) const {
Variant result; ManuallyInitializedValue<Variant> result;
GDExtensionBool valid; GDExtensionBool valid;
GDExtensionBool oob; GDExtensionBool oob;
internal::gdextension_interface_variant_get_indexed(_native_ptr(), index, result._native_ptr(), &valid, &oob); internal::gdextension_interface_variant_get_indexed(_native_ptr(), index, result.ptr(), &valid, &oob);
r_valid = PtrToArg<bool>::convert(&valid); r_valid = PtrToArg<bool>::convert(&valid);
r_oob = PtrToArg<bool>::convert(&oob); r_oob = PtrToArg<bool>::convert(&oob);
return result; return result.get();
} }
Variant Variant::get_keyed(const Variant &key, bool &r_valid) const { Variant Variant::get_keyed(const Variant &key, bool &r_valid) const {
Variant result; ManuallyInitializedValue<Variant> result;
GDExtensionBool valid; GDExtensionBool valid;
internal::gdextension_interface_variant_get_keyed(_native_ptr(), key._native_ptr(), result._native_ptr(), &valid); internal::gdextension_interface_variant_get_keyed(_native_ptr(), key._native_ptr(), result.ptr(), &valid);
r_valid = PtrToArg<bool>::convert(&valid); r_valid = PtrToArg<bool>::convert(&valid);
return result; return result.get();
} }
bool Variant::in(const Variant &index, bool *r_valid) const { bool Variant::in(const Variant &index, bool *r_valid) const {