Browse Source

Improve user-friendliness of "return value as function param" pattern in GDExtension API

This commit introduce separate types (e.g. GDNativeStringPtr vs GDNativeUninitializedStringPtr)
depending on if the pointed data is already initialized (C++ style where constructor is alway
called when create a variable even if it is to be passed as return value) or not (C style).
On top of that, small changes has been made to `GDNativeInterface` so that it methods are
consistent on using uninitialized return value.
Emmanuel Leblond 2 years ago
parent
commit
e785dd9dd9

+ 2 - 2
core/extension/gdextension.cpp

@@ -425,10 +425,10 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra
 	self->extension_classes.erase(class_name);
 	self->extension_classes.erase(class_name);
 }
 }
 
 
-void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path) {
+void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionUninitializedStringPtr r_path) {
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 
 
-	*(String *)r_path = self->library_path;
+	memnew_placement(r_path, String(self->library_path));
 }
 }
 
 
 Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) {
 Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol) {

+ 59 - 67
core/extension/gdextension_interface.cpp

@@ -80,10 +80,10 @@ uint64_t gdextension_get_native_struct_size(GDExtensionConstStringNamePtr p_name
 
 
 // Variant functions
 // Variant functions
 
 
-static void gdextension_variant_new_copy(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src) {
+static void gdextension_variant_new_copy(GDExtensionUninitializedVariantPtr r_dest, GDExtensionConstVariantPtr p_src) {
 	memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<const Variant *>(p_src)));
 	memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant(*reinterpret_cast<const Variant *>(p_src)));
 }
 }
-static void gdextension_variant_new_nil(GDExtensionVariantPtr r_dest) {
+static void gdextension_variant_new_nil(GDExtensionUninitializedVariantPtr r_dest) {
 	memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant);
 	memnew_placement(reinterpret_cast<Variant *>(r_dest), Variant);
 }
 }
 static void gdextension_variant_destroy(GDExtensionVariantPtr p_self) {
 static void gdextension_variant_destroy(GDExtensionVariantPtr p_self) {
@@ -92,14 +92,14 @@ static void gdextension_variant_destroy(GDExtensionVariantPtr p_self) {
 
 
 // variant type
 // variant type
 
 
-static void gdextension_variant_call(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
+static void gdextension_variant_call(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error) {
 	Variant *self = (Variant *)p_self;
 	Variant *self = (Variant *)p_self;
 	const StringName method = *reinterpret_cast<const StringName *>(p_method);
 	const StringName method = *reinterpret_cast<const StringName *>(p_method);
 	const Variant **args = (const Variant **)p_args;
 	const Variant **args = (const Variant **)p_args;
-	Variant ret;
 	Callable::CallError error;
 	Callable::CallError error;
-	self->callp(method, args, p_argcount, ret, error);
-	memnew_placement(r_return, Variant(ret));
+	memnew_placement(r_return, Variant);
+	Variant *ret = reinterpret_cast<Variant *>(r_return);
+	self->callp(method, args, p_argcount, *ret, error);
 
 
 	if (r_error) {
 	if (r_error) {
 		r_error->error = (GDExtensionCallErrorType)(error.error);
 		r_error->error = (GDExtensionCallErrorType)(error.error);
@@ -108,14 +108,14 @@ static void gdextension_variant_call(GDExtensionVariantPtr p_self, GDExtensionCo
 	}
 	}
 }
 }
 
 
-static void gdextension_variant_call_static(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
+static void gdextension_variant_call_static(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argcount, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error) {
 	Variant::Type type = (Variant::Type)p_type;
 	Variant::Type type = (Variant::Type)p_type;
 	const StringName method = *reinterpret_cast<const StringName *>(p_method);
 	const StringName method = *reinterpret_cast<const StringName *>(p_method);
 	const Variant **args = (const Variant **)p_args;
 	const Variant **args = (const Variant **)p_args;
-	Variant ret;
 	Callable::CallError error;
 	Callable::CallError error;
-	Variant::call_static(type, method, args, p_argcount, ret, error);
-	memnew_placement(r_return, Variant(ret));
+	memnew_placement(r_return, Variant);
+	Variant *ret = reinterpret_cast<Variant *>(r_return);
+	Variant::call_static(type, method, args, p_argcount, *ret, error);
 
 
 	if (r_error) {
 	if (r_error) {
 		r_error->error = (GDExtensionCallErrorType)error.error;
 		r_error->error = (GDExtensionCallErrorType)error.error;
@@ -124,12 +124,13 @@ static void gdextension_variant_call_static(GDExtensionVariantType p_type, GDExt
 	}
 	}
 }
 }
 
 
-static void gdextension_variant_evaluate(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid) {
+static void gdextension_variant_evaluate(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionUninitializedVariantPtr r_return, GDExtensionBool *r_valid) {
 	Variant::Operator op = (Variant::Operator)p_op;
 	Variant::Operator op = (Variant::Operator)p_op;
 	const Variant *a = (const Variant *)p_a;
 	const Variant *a = (const Variant *)p_a;
 	const Variant *b = (const Variant *)p_b;
 	const Variant *b = (const Variant *)p_b;
-	Variant *ret = (Variant *)r_return;
 	bool valid;
 	bool valid;
+	memnew_placement(r_return, Variant);
+	Variant *ret = reinterpret_cast<Variant *>(r_return);
 	Variant::evaluate(op, *a, *b, *ret, valid);
 	Variant::evaluate(op, *a, *b, *ret, valid);
 	*r_valid = valid;
 	*r_valid = valid;
 }
 }
@@ -175,7 +176,7 @@ static void gdextension_variant_set_indexed(GDExtensionVariantPtr p_self, GDExte
 	*r_oob = oob;
 	*r_oob = oob;
 }
 }
 
 
-static void gdextension_variant_get(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+static void gdextension_variant_get(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 	const Variant *key = (const Variant *)p_key;
 	const Variant *key = (const Variant *)p_key;
 
 
@@ -184,7 +185,7 @@ static void gdextension_variant_get(GDExtensionConstVariantPtr p_self, GDExtensi
 	*r_valid = valid;
 	*r_valid = valid;
 }
 }
 
 
-static void gdextension_variant_get_named(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+static void gdextension_variant_get_named(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 	const StringName *key = (const StringName *)p_key;
 	const StringName *key = (const StringName *)p_key;
 
 
@@ -193,7 +194,7 @@ static void gdextension_variant_get_named(GDExtensionConstVariantPtr p_self, GDE
 	*r_valid = valid;
 	*r_valid = valid;
 }
 }
 
 
-static void gdextension_variant_get_keyed(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+static void gdextension_variant_get_keyed(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 	const Variant *key = (const Variant *)p_key;
 	const Variant *key = (const Variant *)p_key;
 
 
@@ -202,7 +203,7 @@ static void gdextension_variant_get_keyed(GDExtensionConstVariantPtr p_self, GDE
 	*r_valid = valid;
 	*r_valid = valid;
 }
 }
 
 
-static void gdextension_variant_get_indexed(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob) {
+static void gdextension_variant_get_indexed(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 
 
 	bool valid;
 	bool valid;
@@ -213,9 +214,10 @@ static void gdextension_variant_get_indexed(GDExtensionConstVariantPtr p_self, G
 }
 }
 
 
 /// Iteration.
 /// Iteration.
-static GDExtensionBool gdextension_variant_iter_init(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid) {
+static GDExtensionBool gdextension_variant_iter_init(GDExtensionConstVariantPtr p_self, GDExtensionUninitializedVariantPtr r_iter, GDExtensionBool *r_valid) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
-	Variant *iter = (Variant *)r_iter;
+	memnew_placement(r_iter, Variant);
+	Variant *iter = reinterpret_cast<Variant *>(r_iter);
 
 
 	bool valid;
 	bool valid;
 	bool ret = self->iter_init(*iter, valid);
 	bool ret = self->iter_init(*iter, valid);
@@ -233,7 +235,7 @@ static GDExtensionBool gdextension_variant_iter_next(GDExtensionConstVariantPtr
 	return ret;
 	return ret;
 }
 }
 
 
-static void gdextension_variant_iter_get(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid) {
+static void gdextension_variant_iter_get(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 	Variant *iter = (Variant *)r_iter;
 	Variant *iter = (Variant *)r_iter;
 
 
@@ -264,12 +266,12 @@ static GDExtensionBool gdextension_variant_booleanize(GDExtensionConstVariantPtr
 	return self->booleanize();
 	return self->booleanize();
 }
 }
 
 
-static void gdextension_variant_duplicate(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep) {
+static void gdextension_variant_duplicate(GDExtensionConstVariantPtr p_self, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool p_deep) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 	memnew_placement(r_ret, Variant(self->duplicate(p_deep)));
 	memnew_placement(r_ret, Variant(self->duplicate(p_deep)));
 }
 }
 
 
-static void gdextension_variant_stringify(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret) {
+static void gdextension_variant_stringify(GDExtensionConstVariantPtr p_self, GDExtensionUninitializedVariantPtr r_ret) {
 	const Variant *self = (const Variant *)p_self;
 	const Variant *self = (const Variant *)p_self;
 	memnew_placement(r_ret, String(*self));
 	memnew_placement(r_ret, String(*self));
 }
 }
@@ -298,7 +300,7 @@ static GDExtensionBool gdextension_variant_has_key(GDExtensionConstVariantPtr p_
 	return ret;
 	return ret;
 }
 }
 
 
-static void gdextension_variant_get_type_name(GDExtensionVariantType p_type, GDExtensionStringPtr r_ret) {
+static void gdextension_variant_get_type_name(GDExtensionVariantType p_type, GDExtensionUninitializedVariantPtr r_ret) {
 	String name = Variant::get_type_name((Variant::Type)p_type);
 	String name = Variant::get_type_name((Variant::Type)p_type);
 	memnew_placement(r_ret, String(name));
 	memnew_placement(r_ret, String(name));
 }
 }
@@ -498,11 +500,12 @@ static GDExtensionPtrConstructor gdextension_variant_get_ptr_constructor(GDExten
 static GDExtensionPtrDestructor gdextension_variant_get_ptr_destructor(GDExtensionVariantType p_type) {
 static GDExtensionPtrDestructor gdextension_variant_get_ptr_destructor(GDExtensionVariantType p_type) {
 	return (GDExtensionPtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type));
 	return (GDExtensionPtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type));
 }
 }
-static void gdextension_variant_construct(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error) {
-	memnew_placement(p_base, Variant);
+static void gdextension_variant_construct(GDExtensionVariantType p_type, GDExtensionUninitializedVariantPtr r_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error) {
+	memnew_placement(r_base, Variant);
+	Variant *base = reinterpret_cast<Variant *>(r_base);
 
 
 	Callable::CallError error;
 	Callable::CallError error;
-	Variant::construct(Variant::Type(p_type), *(Variant *)p_base, (const Variant **)p_args, p_argument_count, error);
+	Variant::construct(Variant::Type(p_type), *base, (const Variant **)p_args, p_argument_count, error);
 
 
 	if (r_error) {
 	if (r_error) {
 		r_error->error = (GDExtensionCallErrorType)(error.error);
 		r_error->error = (GDExtensionCallErrorType)(error.error);
@@ -533,7 +536,7 @@ static GDExtensionPtrKeyedGetter gdextension_variant_get_ptr_keyed_getter(GDExte
 static GDExtensionPtrKeyedChecker gdextension_variant_get_ptr_keyed_checker(GDExtensionVariantType p_type) {
 static GDExtensionPtrKeyedChecker gdextension_variant_get_ptr_keyed_checker(GDExtensionVariantType p_type) {
 	return (GDExtensionPtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
 	return (GDExtensionPtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
 }
 }
-static void gdextension_variant_get_constant_value(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret) {
+static void gdextension_variant_get_constant_value(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionUninitializedVariantPtr r_ret) {
 	StringName constant = *reinterpret_cast<const StringName *>(p_constant);
 	StringName constant = *reinterpret_cast<const StringName *>(p_constant);
 	memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant)));
 	memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant)));
 }
 }
@@ -549,77 +552,67 @@ static GDExtensionPtrUtilityFunction gdextension_variant_get_ptr_utility_functio
 
 
 //string helpers
 //string helpers
 
 
-static void gdextension_string_new_with_latin1_chars(GDExtensionStringPtr r_dest, const char *p_contents) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
-	*dest = String(p_contents);
+static void gdextension_string_new_with_latin1_chars(GDExtensionUninitializedStringPtr r_dest, const char *p_contents) {
+	memnew_placement(r_dest, String(p_contents));
 }
 }
 
 
-static void gdextension_string_new_with_utf8_chars(GDExtensionStringPtr r_dest, const char *p_contents) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
+static void gdextension_string_new_with_utf8_chars(GDExtensionUninitializedStringPtr r_dest, const char *p_contents) {
+	memnew_placement(r_dest, String);
+	String *dest = reinterpret_cast<String *>(r_dest);
 	dest->parse_utf8(p_contents);
 	dest->parse_utf8(p_contents);
 }
 }
 
 
-static void gdextension_string_new_with_utf16_chars(GDExtensionStringPtr r_dest, const char16_t *p_contents) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
+static void gdextension_string_new_with_utf16_chars(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents) {
+	memnew_placement(r_dest, String);
+	String *dest = reinterpret_cast<String *>(r_dest);
 	dest->parse_utf16(p_contents);
 	dest->parse_utf16(p_contents);
 }
 }
 
 
-static void gdextension_string_new_with_utf32_chars(GDExtensionStringPtr 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 gdextension_string_new_with_utf32_chars(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents) {
+	memnew_placement(r_dest, String((const char32_t *)p_contents));
 }
 }
 
 
-static void gdextension_string_new_with_wide_chars(GDExtensionStringPtr r_dest, const wchar_t *p_contents) {
-	String *dest = (String *)r_dest;
+static void gdextension_string_new_with_wide_chars(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents) {
 	if constexpr (sizeof(wchar_t) == 2) {
 	if constexpr (sizeof(wchar_t) == 2) {
 		// wchar_t is 16 bit, parse.
 		// wchar_t is 16 bit, parse.
-		memnew_placement(dest, String);
+		memnew_placement(r_dest, String);
+		String *dest = reinterpret_cast<String *>(r_dest);
 		dest->parse_utf16((const char16_t *)p_contents);
 		dest->parse_utf16((const char16_t *)p_contents);
 	} else {
 	} else {
 		// wchar_t is 32 bit, copy.
 		// wchar_t is 32 bit, copy.
-		memnew_placement(dest, String);
-		*dest = String((const char32_t *)p_contents);
+		memnew_placement(r_dest, String((const char32_t *)p_contents));
 	}
 	}
 }
 }
 
 
-static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
-	*dest = String(p_contents, p_size);
+static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
+	memnew_placement(r_dest, String(p_contents, p_size));
 }
 }
 
 
-static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
+static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
+	memnew_placement(r_dest, String);
+	String *dest = reinterpret_cast<String *>(r_dest);
 	dest->parse_utf8(p_contents, p_size);
 	dest->parse_utf8(p_contents, p_size);
 }
 }
 
 
-static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
+static void gdextension_string_new_with_utf16_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size) {
+	memnew_placement(r_dest, String);
+	String *dest = reinterpret_cast<String *>(r_dest);
 	dest->parse_utf16(p_contents, p_size);
 	dest->parse_utf16(p_contents, p_size);
 }
 }
 
 
-static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size) {
-	String *dest = (String *)r_dest;
-	memnew_placement(dest, String);
-	*dest = String((const char32_t *)p_contents, p_size);
+static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size) {
+	memnew_placement(r_dest, String((const char32_t *)p_contents, p_size));
 }
 }
 
 
-static void gdextension_string_new_with_wide_chars_and_len(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size) {
-	String *dest = (String *)r_dest;
+static void gdextension_string_new_with_wide_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size) {
 	if constexpr (sizeof(wchar_t) == 2) {
 	if constexpr (sizeof(wchar_t) == 2) {
 		// wchar_t is 16 bit, parse.
 		// wchar_t is 16 bit, parse.
-		memnew_placement(dest, String);
+		memnew_placement(r_dest, String);
+		String *dest = reinterpret_cast<String *>(r_dest);
 		dest->parse_utf16((const char16_t *)p_contents, p_size);
 		dest->parse_utf16((const char16_t *)p_contents, p_size);
 	} else {
 	} else {
 		// wchar_t is 32 bit, copy.
 		// wchar_t is 32 bit, copy.
-		memnew_placement(dest, String);
-		*dest = String((const char32_t *)p_contents, p_size);
+		memnew_placement(r_dest, String((const char32_t *)p_contents, p_size));
 	}
 	}
 }
 }
 
 
@@ -936,14 +929,13 @@ static GDExtensionVariantPtr gdextension_dictionary_operator_index_const(GDExten
 
 
 /* OBJECT API */
 /* OBJECT API */
 
 
-static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) {
+static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error) {
 	const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind);
 	const MethodBind *mb = reinterpret_cast<const MethodBind *>(p_method_bind);
 	Object *o = (Object *)p_instance;
 	Object *o = (Object *)p_instance;
 	const Variant **args = (const Variant **)p_args;
 	const Variant **args = (const Variant **)p_args;
 	Callable::CallError error;
 	Callable::CallError error;
 
 
-	Variant ret = mb->call(o, args, p_arg_count, error);
-	memnew_placement(r_return, Variant(ret));
+	memnew_placement(r_return, Variant(mb->call(o, args, p_arg_count, error)));
 
 
 	if (r_error) {
 	if (r_error) {
 		r_error->error = (GDExtensionCallErrorType)(error.error);
 		r_error->error = (GDExtensionCallErrorType)(error.error);

+ 49 - 28
core/extension/gdextension_interface.h

@@ -139,16 +139,37 @@ typedef enum {
 
 
 } GDExtensionVariantOperator;
 } GDExtensionVariantOperator;
 
 
+// In this API there are multiple functions which expect the caller to pass a pointer
+// on return value as parameter.
+// In order to make it clear if the caller should initialize the return value or not
+// we have two flavor of types:
+// - `GDExtensionXXXPtr` for pointer on an initialized value
+// - `GDExtensionUninitializedXXXPtr` for pointer on uninitialized value
+//
+// Notes:
+// - Not respecting those requirements can seems harmless, but will lead to unexpected
+//   segfault or memory leak (for instance with a specific compiler/OS, or when two
+//   native extensions start doing ptrcall on each other).
+// - Initialization must be done with the function pointer returned by `variant_get_ptr_constructor`,
+//   zero-initializing the variable should not be considered a valid initialization method here !
+// - Some types have no destructor (see `extension_api.json`'s `has_destructor` field), for
+//   them it is always safe to skip the constructor for the return value if you are in a hurry ;-)
+
 typedef void *GDExtensionVariantPtr;
 typedef void *GDExtensionVariantPtr;
 typedef const void *GDExtensionConstVariantPtr;
 typedef const void *GDExtensionConstVariantPtr;
+typedef void *GDExtensionUninitializedVariantPtr;
 typedef void *GDExtensionStringNamePtr;
 typedef void *GDExtensionStringNamePtr;
 typedef const void *GDExtensionConstStringNamePtr;
 typedef const void *GDExtensionConstStringNamePtr;
+typedef void *GDExtensionUninitializedStringNamePtr;
 typedef void *GDExtensionStringPtr;
 typedef void *GDExtensionStringPtr;
 typedef const void *GDExtensionConstStringPtr;
 typedef const void *GDExtensionConstStringPtr;
+typedef void *GDExtensionUninitializedStringPtr;
 typedef void *GDExtensionObjectPtr;
 typedef void *GDExtensionObjectPtr;
 typedef const void *GDExtensionConstObjectPtr;
 typedef const void *GDExtensionConstObjectPtr;
+typedef void *GDExtensionUninitializedObjectPtr;
 typedef void *GDExtensionTypePtr;
 typedef void *GDExtensionTypePtr;
 typedef const void *GDExtensionConstTypePtr;
 typedef const void *GDExtensionConstTypePtr;
+typedef void *GDExtensionUninitializedTypePtr;
 typedef const void *GDExtensionMethodBindPtr;
 typedef const void *GDExtensionMethodBindPtr;
 typedef int64_t GDExtensionInt;
 typedef int64_t GDExtensionInt;
 typedef uint8_t GDExtensionBool;
 typedef uint8_t GDExtensionBool;
@@ -427,37 +448,37 @@ typedef struct {
 	/* GODOT VARIANT */
 	/* GODOT VARIANT */
 
 
 	/* variant general */
 	/* variant general */
-	void (*variant_new_copy)(GDExtensionVariantPtr r_dest, GDExtensionConstVariantPtr p_src);
-	void (*variant_new_nil)(GDExtensionVariantPtr r_dest);
+	void (*variant_new_copy)(GDExtensionUninitializedVariantPtr r_dest, GDExtensionConstVariantPtr p_src);
+	void (*variant_new_nil)(GDExtensionUninitializedVariantPtr r_dest);
 	void (*variant_destroy)(GDExtensionVariantPtr p_self);
 	void (*variant_destroy)(GDExtensionVariantPtr p_self);
 
 
 	/* variant type */
 	/* variant type */
-	void (*variant_call)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
-	void (*variant_call_static)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
-	void (*variant_evaluate)(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionVariantPtr r_return, GDExtensionBool *r_valid);
+	void (*variant_call)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error);
+	void (*variant_call_static)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error);
+	void (*variant_evaluate)(GDExtensionVariantOperator p_op, GDExtensionConstVariantPtr p_a, GDExtensionConstVariantPtr p_b, GDExtensionUninitializedVariantPtr r_return, GDExtensionBool *r_valid);
 	void (*variant_set)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
 	void (*variant_set)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
 	void (*variant_set_named)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
 	void (*variant_set_named)(GDExtensionVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
 	void (*variant_set_keyed)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
 	void (*variant_set_keyed)(GDExtensionVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid);
 	void (*variant_set_indexed)(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob);
 	void (*variant_set_indexed)(GDExtensionVariantPtr p_self, GDExtensionInt p_index, GDExtensionConstVariantPtr p_value, GDExtensionBool *r_valid, GDExtensionBool *r_oob);
-	void (*variant_get)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
-	void (*variant_get_named)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
-	void (*variant_get_keyed)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
-	void (*variant_get_indexed)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob);
-	GDExtensionBool (*variant_iter_init)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid);
+	void (*variant_get)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid);
+	void (*variant_get_named)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_key, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid);
+	void (*variant_get_keyed)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid);
+	void (*variant_get_indexed)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_index, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid, GDExtensionBool *r_oob);
+	GDExtensionBool (*variant_iter_init)(GDExtensionConstVariantPtr p_self, GDExtensionUninitializedVariantPtr r_iter, GDExtensionBool *r_valid);
 	GDExtensionBool (*variant_iter_next)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid);
 	GDExtensionBool (*variant_iter_next)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionBool *r_valid);
-	void (*variant_iter_get)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionVariantPtr r_ret, GDExtensionBool *r_valid);
+	void (*variant_iter_get)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_iter, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool *r_valid);
 	GDExtensionInt (*variant_hash)(GDExtensionConstVariantPtr p_self);
 	GDExtensionInt (*variant_hash)(GDExtensionConstVariantPtr p_self);
 	GDExtensionInt (*variant_recursive_hash)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count);
 	GDExtensionInt (*variant_recursive_hash)(GDExtensionConstVariantPtr p_self, GDExtensionInt p_recursion_count);
 	GDExtensionBool (*variant_hash_compare)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other);
 	GDExtensionBool (*variant_hash_compare)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_other);
 	GDExtensionBool (*variant_booleanize)(GDExtensionConstVariantPtr p_self);
 	GDExtensionBool (*variant_booleanize)(GDExtensionConstVariantPtr p_self);
-	void (*variant_duplicate)(GDExtensionConstVariantPtr p_self, GDExtensionVariantPtr r_ret, GDExtensionBool p_deep);
-	void (*variant_stringify)(GDExtensionConstVariantPtr p_self, GDExtensionStringPtr r_ret);
+	void (*variant_duplicate)(GDExtensionConstVariantPtr p_self, GDExtensionUninitializedVariantPtr r_ret, GDExtensionBool p_deep);
+	void (*variant_stringify)(GDExtensionConstVariantPtr p_self, GDExtensionUninitializedStringPtr r_ret);
 
 
 	GDExtensionVariantType (*variant_get_type)(GDExtensionConstVariantPtr p_self);
 	GDExtensionVariantType (*variant_get_type)(GDExtensionConstVariantPtr p_self);
 	GDExtensionBool (*variant_has_method)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method);
 	GDExtensionBool (*variant_has_method)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method);
 	GDExtensionBool (*variant_has_member)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
 	GDExtensionBool (*variant_has_member)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
 	GDExtensionBool (*variant_has_key)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid);
 	GDExtensionBool (*variant_has_key)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid);
-	void (*variant_get_type_name)(GDExtensionVariantType p_type, GDExtensionStringPtr r_name);
+	void (*variant_get_type_name)(GDExtensionVariantType p_type, GDExtensionUninitializedStringPtr r_name);
 	GDExtensionBool (*variant_can_convert)(GDExtensionVariantType p_from, GDExtensionVariantType p_to);
 	GDExtensionBool (*variant_can_convert)(GDExtensionVariantType p_from, GDExtensionVariantType p_to);
 	GDExtensionBool (*variant_can_convert_strict)(GDExtensionVariantType p_from, GDExtensionVariantType p_to);
 	GDExtensionBool (*variant_can_convert_strict)(GDExtensionVariantType p_from, GDExtensionVariantType p_to);
 
 
@@ -468,7 +489,7 @@ typedef struct {
 	GDExtensionPtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash);
 	GDExtensionPtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash);
 	GDExtensionPtrConstructor (*variant_get_ptr_constructor)(GDExtensionVariantType p_type, int32_t p_constructor);
 	GDExtensionPtrConstructor (*variant_get_ptr_constructor)(GDExtensionVariantType p_type, int32_t p_constructor);
 	GDExtensionPtrDestructor (*variant_get_ptr_destructor)(GDExtensionVariantType p_type);
 	GDExtensionPtrDestructor (*variant_get_ptr_destructor)(GDExtensionVariantType p_type);
-	void (*variant_construct)(GDExtensionVariantType p_type, GDExtensionVariantPtr p_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error);
+	void (*variant_construct)(GDExtensionVariantType p_type, GDExtensionUninitializedVariantPtr r_base, const GDExtensionConstVariantPtr *p_args, int32_t p_argument_count, GDExtensionCallError *r_error);
 	GDExtensionPtrSetter (*variant_get_ptr_setter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
 	GDExtensionPtrSetter (*variant_get_ptr_setter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
 	GDExtensionPtrGetter (*variant_get_ptr_getter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
 	GDExtensionPtrGetter (*variant_get_ptr_getter)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
 	GDExtensionPtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDExtensionVariantType p_type);
 	GDExtensionPtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDExtensionVariantType p_type);
@@ -476,20 +497,20 @@ typedef struct {
 	GDExtensionPtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDExtensionVariantType p_type);
 	GDExtensionPtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDExtensionVariantType p_type);
 	GDExtensionPtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDExtensionVariantType p_type);
 	GDExtensionPtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDExtensionVariantType p_type);
 	GDExtensionPtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDExtensionVariantType p_type);
 	GDExtensionPtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDExtensionVariantType p_type);
-	void (*variant_get_constant_value)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionVariantPtr r_ret);
+	void (*variant_get_constant_value)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_constant, GDExtensionUninitializedVariantPtr r_ret);
 	GDExtensionPtrUtilityFunction (*variant_get_ptr_utility_function)(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash);
 	GDExtensionPtrUtilityFunction (*variant_get_ptr_utility_function)(GDExtensionConstStringNamePtr p_function, GDExtensionInt p_hash);
 
 
 	/*  extra utilities */
 	/*  extra utilities */
-	void (*string_new_with_latin1_chars)(GDExtensionStringPtr r_dest, const char *p_contents);
-	void (*string_new_with_utf8_chars)(GDExtensionStringPtr r_dest, const char *p_contents);
-	void (*string_new_with_utf16_chars)(GDExtensionStringPtr r_dest, const char16_t *p_contents);
-	void (*string_new_with_utf32_chars)(GDExtensionStringPtr r_dest, const char32_t *p_contents);
-	void (*string_new_with_wide_chars)(GDExtensionStringPtr r_dest, const wchar_t *p_contents);
-	void (*string_new_with_latin1_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
-	void (*string_new_with_utf8_chars_and_len)(GDExtensionStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
-	void (*string_new_with_utf16_chars_and_len)(GDExtensionStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size);
-	void (*string_new_with_utf32_chars_and_len)(GDExtensionStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size);
-	void (*string_new_with_wide_chars_and_len)(GDExtensionStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size);
+	void (*string_new_with_latin1_chars)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents);
+	void (*string_new_with_utf8_chars)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents);
+	void (*string_new_with_utf16_chars)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents);
+	void (*string_new_with_utf32_chars)(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents);
+	void (*string_new_with_wide_chars)(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents);
+	void (*string_new_with_latin1_chars_and_len)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
+	void (*string_new_with_utf8_chars_and_len)(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size);
+	void (*string_new_with_utf16_chars_and_len)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_size);
+	void (*string_new_with_utf32_chars_and_len)(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_size);
+	void (*string_new_with_wide_chars_and_len)(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_size);
 	/* Information about the following functions:
 	/* Information about the following functions:
 	 * - The return value is the resulting encoded string length.
 	 * - 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.
 	 * - The length returned is in characters, not in bytes. It also does not include a trailing zero.
@@ -564,7 +585,7 @@ typedef struct {
 
 
 	/* OBJECT */
 	/* OBJECT */
 
 
-	void (*object_method_bind_call)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionVariantPtr r_ret, GDExtensionCallError *r_error);
+	void (*object_method_bind_call)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionUninitializedVariantPtr r_ret, GDExtensionCallError *r_error);
 	void (*object_method_bind_ptrcall)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
 	void (*object_method_bind_ptrcall)(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
 	void (*object_destroy)(GDExtensionObjectPtr p_o);
 	void (*object_destroy)(GDExtensionObjectPtr p_o);
 	GDExtensionObjectPtr (*global_get_singleton)(GDExtensionConstStringNamePtr p_name);
 	GDExtensionObjectPtr (*global_get_singleton)(GDExtensionConstStringNamePtr p_name);
@@ -605,7 +626,7 @@ typedef struct {
 	void (*classdb_register_extension_class_signal)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
 	void (*classdb_register_extension_class_signal)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_signal_name, const GDExtensionPropertyInfo *p_argument_info, GDExtensionInt p_argument_count);
 	void (*classdb_unregister_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
 	void (*classdb_unregister_extension_class)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr 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)(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
+	void (*get_library_path)(GDExtensionClassLibraryPtr p_library, GDExtensionUninitializedStringPtr r_path);
 
 
 } GDExtensionInterface;
 } GDExtensionInterface;
 
 

+ 6 - 6
core/variant/variant_internal.h

@@ -1534,14 +1534,14 @@ struct VariantTypeAdjust<Object *> {
 
 
 template <class T>
 template <class T>
 struct VariantTypeConstructor {
 struct VariantTypeConstructor {
-	_FORCE_INLINE_ static void variant_from_type(void *p_variant, void *p_value) {
-		Variant *variant = reinterpret_cast<Variant *>(p_variant);
-		VariantInitializer<T>::init(variant);
-		VariantInternalAccessor<T>::set(variant, *((T *)p_value));
+	_FORCE_INLINE_ static void variant_from_type(void *r_variant, void *p_value) {
+		// r_variant is provided by caller as uninitialized memory
+		memnew_placement(r_variant, Variant(*((T *)p_value)));
 	}
 	}
 
 
-	_FORCE_INLINE_ static void type_from_variant(void *p_value, void *p_variant) {
-		*((T *)p_value) = VariantInternalAccessor<T>::get(reinterpret_cast<Variant *>(p_variant));
+	_FORCE_INLINE_ static void type_from_variant(void *r_value, void *p_variant) {
+		// r_value is provided by caller as uninitialized memory
+		memnew_placement(r_value, T(VariantInternalAccessor<T>::get(reinterpret_cast<Variant *>(p_variant))));
 	}
 	}
 };
 };