Improve extension system

- Fix library loading and initialization.
- Add extra methods/parameters in the interface needed by extenstions.
- Add Variant destructors and functions for extracting values and
  creating Variants from values.
This commit is contained in:
George Marques 2021-07-29 10:53:05 -03:00
parent 97947bc063
commit 3f362cec68
No known key found for this signature in database
GPG key ID: 046BD46A3201E43D
12 changed files with 402 additions and 26 deletions

View file

@ -559,6 +559,10 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
d["constructors"] = constructors;
}
}
{
//destructor
d["has_destructor"] = Variant::has_destructor(type);
}
builtins.push_back(d);
}

View file

@ -299,6 +299,161 @@ static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_fr
return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to);
}
// Variant interaction.
static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_constructor(GDNativeVariantType p_type) {
switch (p_type) {
case GDNATIVE_VARIANT_TYPE_BOOL:
return VariantTypeConstructor<bool>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_INT:
return VariantTypeConstructor<int64_t>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_FLOAT:
return VariantTypeConstructor<double>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_STRING:
return VariantTypeConstructor<String>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_VECTOR2:
return VariantTypeConstructor<Vector2>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_VECTOR2I:
return VariantTypeConstructor<Vector2i>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_RECT2:
return VariantTypeConstructor<Rect2>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_RECT2I:
return VariantTypeConstructor<Rect2i>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_VECTOR3:
return VariantTypeConstructor<Vector3>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_VECTOR3I:
return VariantTypeConstructor<Vector3i>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_TRANSFORM2D:
return VariantTypeConstructor<Transform2D>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PLANE:
return VariantTypeConstructor<Plane>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_QUATERNION:
return VariantTypeConstructor<Quaternion>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_AABB:
return VariantTypeConstructor<AABB>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_BASIS:
return VariantTypeConstructor<Basis>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_TRANSFORM3D:
return VariantTypeConstructor<Transform3D>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_COLOR:
return VariantTypeConstructor<Color>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_STRING_NAME:
return VariantTypeConstructor<StringName>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_NODE_PATH:
return VariantTypeConstructor<NodePath>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_RID:
return VariantTypeConstructor<RID>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_OBJECT:
return VariantTypeConstructor<Object *>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_CALLABLE:
return VariantTypeConstructor<Callable>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_SIGNAL:
return VariantTypeConstructor<Signal>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_DICTIONARY:
return VariantTypeConstructor<Dictionary>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_ARRAY:
return VariantTypeConstructor<Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY:
return VariantTypeConstructor<PackedByteArray>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY:
return VariantTypeConstructor<PackedInt32Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY:
return VariantTypeConstructor<PackedInt64Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
return VariantTypeConstructor<PackedFloat32Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
return VariantTypeConstructor<PackedFloat64Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY:
return VariantTypeConstructor<PackedStringArray>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
return VariantTypeConstructor<PackedVector2Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
return VariantTypeConstructor<PackedVector3Array>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY:
return VariantTypeConstructor<PackedColorArray>::variant_from_type;
case GDNATIVE_VARIANT_TYPE_NIL:
case GDNATIVE_VARIANT_TYPE_VARIANT_MAX:
ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
}
ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
}
static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_constructor(GDNativeVariantType p_type) {
switch (p_type) {
case GDNATIVE_VARIANT_TYPE_BOOL:
return VariantTypeConstructor<bool>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_INT:
return VariantTypeConstructor<int64_t>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_FLOAT:
return VariantTypeConstructor<double>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_STRING:
return VariantTypeConstructor<String>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_VECTOR2:
return VariantTypeConstructor<Vector2>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_VECTOR2I:
return VariantTypeConstructor<Vector2i>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_RECT2:
return VariantTypeConstructor<Rect2>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_RECT2I:
return VariantTypeConstructor<Rect2i>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_VECTOR3:
return VariantTypeConstructor<Vector3>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_VECTOR3I:
return VariantTypeConstructor<Vector3i>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_TRANSFORM2D:
return VariantTypeConstructor<Transform2D>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PLANE:
return VariantTypeConstructor<Plane>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_QUATERNION:
return VariantTypeConstructor<Quaternion>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_AABB:
return VariantTypeConstructor<AABB>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_BASIS:
return VariantTypeConstructor<Basis>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_TRANSFORM3D:
return VariantTypeConstructor<Transform3D>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_COLOR:
return VariantTypeConstructor<Color>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_STRING_NAME:
return VariantTypeConstructor<StringName>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_NODE_PATH:
return VariantTypeConstructor<NodePath>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_RID:
return VariantTypeConstructor<RID>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_OBJECT:
return VariantTypeConstructor<Object *>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_CALLABLE:
return VariantTypeConstructor<Callable>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_SIGNAL:
return VariantTypeConstructor<Signal>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_DICTIONARY:
return VariantTypeConstructor<Dictionary>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_ARRAY:
return VariantTypeConstructor<Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY:
return VariantTypeConstructor<PackedByteArray>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY:
return VariantTypeConstructor<PackedInt32Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY:
return VariantTypeConstructor<PackedInt64Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
return VariantTypeConstructor<PackedFloat32Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
return VariantTypeConstructor<PackedFloat64Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY:
return VariantTypeConstructor<PackedStringArray>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
return VariantTypeConstructor<PackedVector2Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
return VariantTypeConstructor<PackedVector3Array>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY:
return VariantTypeConstructor<PackedColorArray>::type_from_variant;
case GDNATIVE_VARIANT_TYPE_NIL:
case GDNATIVE_VARIANT_TYPE_VARIANT_MAX:
ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
}
ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
}
// ptrcalls
static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) {
return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
@ -316,6 +471,9 @@ static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNative
static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) {
return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
}
static GDNativePtrDestructor gdnative_variant_get_ptr_destructor(GDNativeVariantType p_type) {
return (GDNativePtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type));
}
static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) {
memnew_placement(p_base, Variant);
@ -521,11 +679,16 @@ static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) {
return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name));
}
static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks) {
static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
Object *o = (Object *)p_instance;
return o->get_instance_binding(p_token, p_callbacks);
}
static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_instance, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
Object *o = (Object *)p_instance;
o->set_instance_binding(p_token, p_binding, p_callbacks);
}
static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
}
@ -626,15 +789,15 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.variant_can_convert = gdnative_variant_can_convert;
gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict;
//ptrcalls
#if 0
GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
#endif
gdni.get_variant_from_type_constructor = gdnative_get_variant_from_type_constructor;
gdni.get_variant_to_type_constructor = gdnative_get_type_from_variant_constructor;
// ptrcalls.
gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator;
gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method;
gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor;
gdni.variant_get_ptr_destructor = gdnative_variant_get_ptr_destructor;
gdni.variant_construct = gdnative_variant_construct;
gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter;
gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter;
@ -672,6 +835,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.object_destroy = gdnative_object_destroy;
gdni.global_get_singleton = gdnative_global_get_singleton;
gdni.object_get_instance_binding = gdnative_object_get_instance_binding;
gdni.object_set_instance_binding = gdnative_object_set_instance_binding;
gdni.object_cast_to = gdnative_object_cast_to;
gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;

View file

@ -39,6 +39,11 @@
#include <stdint.h>
#include <stdio.h>
#ifndef __cplusplus
typedef uint32_t char32_t;
typedef uint16_t char16_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -160,6 +165,7 @@ typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNative
typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result);
typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count);
typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args);
typedef void (*GDNativePtrDestructor)(GDNativeTypePtr p_base);
typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value);
typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value);
typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value);
@ -173,7 +179,7 @@ typedef GDNativeObjectPtr (*GDNativeClassConstructor)();
typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance);
typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_instance, GDNativeBool p_reference);
typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference);
struct GDNativeInstanceBindingCallbacks {
GDNativeInstanceBindingCreateCallback create_callback;
@ -206,6 +212,7 @@ typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
typedef GDExtensionClassInstancePtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassObjectInstance)(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance);
typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
typedef struct {
@ -219,7 +226,8 @@ typedef struct {
GDNativeExtensionClassUnreference unreference_func;
GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
GDNativeExtensionClassGetVirtual get_firtual_func;
GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */
GDNativeExtensionClassGetVirtual get_virtual_func;
void *class_userdata;
} GDNativeExtensionClassCreationInfo;
@ -256,8 +264,8 @@ typedef enum {
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
} GDNativeExtensionClassMethodArgumentMetadata;
typedef void (*GDNativeExtensionClassMethodCall)(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
typedef void (*GDNativeExtensionClassMethodPtrCall)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
/* passing -1 as argument in the following functions refers to the return type */
typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument);
@ -339,6 +347,7 @@ typedef struct {
GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b);
GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash);
GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor);
GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type);
void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error);
GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member);
GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member);
@ -383,7 +392,8 @@ typedef struct {
void (*object_method_bind_ptrcall)(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
void (*object_destroy)(GDNativeObjectPtr p_o);
GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks);
void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);

View file

@ -29,6 +29,7 @@
/*************************************************************************/
#include "native_extension.h"
#include "core/config/project_settings.h"
#include "core/io/config_file.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
@ -69,7 +70,7 @@ public:
Variant ret;
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
GDNativeCallError ce;
call_func(extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
r_error.error = Callable::CallError::Error(ce.error);
r_error.argument = ce.argument;
r_error.expected = ce.expected;
@ -78,7 +79,7 @@ public:
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug.");
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
ptrcall_func(extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
}
virtual bool is_vararg() const {
@ -91,6 +92,7 @@ public:
get_argument_type_func = p_method_info->get_argument_type_func;
get_argument_info_func = p_method_info->get_argument_info_func;
get_argument_metadata_func = p_method_info->get_argument_metadata_func;
set_name(p_method_info->name);
vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG;
@ -109,7 +111,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(String(class_name).is_valid_identifier(), "Attempt to register extension clas '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
Extension *parent_extension = nullptr;
@ -150,6 +152,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
extension->native_extension.unreference = p_extension_funcs->unreference_func;
extension->native_extension.class_userdata = p_extension_funcs->class_userdata;
extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
extension->native_extension.set_object_instance = p_extension_funcs->object_instance_func;
extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
ClassDB::register_extension_class(&extension->native_extension);
@ -159,11 +162,12 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
StringName class_name = p_class_name;
StringName method_name = p_method_info->name;
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info));
method->set_instance_class(class_name);
ClassDB::bind_method_custom(class_name, method);
}
@ -171,7 +175,7 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
@ -181,7 +185,7 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
PropertyInfo pinfo;
@ -199,7 +203,7 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
MethodInfo s;
s.name = p_signal_name;
@ -220,7 +224,7 @@ void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLi
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
Extension *ext = &self->extension_classes[class_name];
ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
@ -368,7 +372,7 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
}
}
if (library_path != String()) {
if (library_path == String()) {
if (r_error) {
*r_error = ERR_FILE_NOT_FOUND;
}
@ -381,7 +385,8 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
Ref<NativeExtension> lib;
lib.instantiate();
err = lib->open_library(library_path, entry_symbol);
String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path);
err = lib->open_library(abs_path, entry_symbol);
if (r_error) {
*r_error = err;

View file

@ -35,8 +35,8 @@
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
class NativeExtension : public RefCounted {
GDCLASS(NativeExtension, RefCounted)
class NativeExtension : public Resource {
GDCLASS(NativeExtension, Resource)
void *library = nullptr; // pointer if valid,

View file

@ -82,6 +82,7 @@ static Ref<ResourceFormatLoaderImage> resource_format_image;
static Ref<TranslationLoaderPO> resource_format_po;
static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
static Ref<NativeExtensionResourceLoader> resource_loader_native_extension;
static _ResourceLoader *_resource_loader = nullptr;
static _ResourceSaver *_resource_saver = nullptr;
@ -234,6 +235,9 @@ void register_core_types() {
native_extension_manager = memnew(NativeExtensionManager);
resource_loader_native_extension.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_native_extension);
ip = IP::create();
_geometry_2d = memnew(_Geometry2D);
@ -298,6 +302,7 @@ void register_core_singletons() {
void register_core_extensions() {
// Hardcoded for now.
NativeExtension::initialize_native_extensions();
if (ProjectSettings::get_singleton()->has_setting("native_extensions/paths")) {
Vector<String> paths = ProjectSettings::get_singleton()->get("native_extensions/paths");
for (int i = 0; i < paths.size(); i++) {
@ -349,6 +354,9 @@ void unregister_core_types() {
memdelete(ip);
}
ResourceLoader::remove_resource_format_loader(resource_loader_native_extension);
resource_loader_native_extension.unref();
ResourceLoader::finalize();
ClassDB::cleanup_defaults();

View file

@ -3533,12 +3533,13 @@ void Variant::register_types() {
_register_variant_methods();
_register_variant_setters_getters();
_register_variant_constructors();
_register_variant_destructors();
_register_variant_utility_functions();
}
void Variant::unregister_types() {
_unregister_variant_operators();
_unregister_variant_methods();
_unregister_variant_setters_getters();
_unregister_variant_constructors();
_unregister_variant_destructors();
_unregister_variant_utility_functions();
}

View file

@ -208,7 +208,7 @@ private:
Transform3D *_transform3d;
PackedArrayRefBase *packed_array;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]{ 0 };
} _data alignas(8);
void reference(const Variant &p_variant);
@ -271,6 +271,8 @@ private:
static void _register_variant_setters_getters();
static void _unregister_variant_setters_getters();
static void _register_variant_constructors();
static void _unregister_variant_destructors();
static void _register_variant_destructors();
static void _unregister_variant_constructors();
static void _register_variant_utility_functions();
static void _unregister_variant_utility_functions();
@ -534,6 +536,14 @@ public:
static void get_constructor_list(Type p_type, List<MethodInfo> *r_list); //convenience
/* Destructors */
// Only ptrcall is available.
typedef void (*PTRDestructor)(void *base);
static PTRDestructor get_ptr_destructor(Variant::Type p_type);
static bool has_destructor(Variant::Type p_type);
/* Properties */
void set_named(const StringName &p_member, const Variant &p_value, bool &r_valid);

View file

@ -0,0 +1,78 @@
/*************************************************************************/
/* variant_destruct.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 "variant_destruct.h"
#include "core/templates/local_vector.h"
static Variant::PTRDestructor destruct_pointers[Variant::VARIANT_MAX] = { nullptr };
template <class T>
static void add_destructor() {
destruct_pointers[T::get_base_type()] = T::ptr_destruct;
}
void Variant::_register_variant_destructors() {
add_destructor<VariantDestruct<String>>();
add_destructor<VariantDestruct<Transform2D>>();
add_destructor<VariantDestruct<::AABB>>();
add_destructor<VariantDestruct<Basis>>();
add_destructor<VariantDestruct<Transform3D>>();
add_destructor<VariantDestruct<StringName>>();
add_destructor<VariantDestruct<NodePath>>();
add_destructor<VariantDestruct<::RID>>();
add_destructor<VariantDestruct<Callable>>();
add_destructor<VariantDestruct<Signal>>();
add_destructor<VariantDestruct<Dictionary>>();
add_destructor<VariantDestruct<Array>>();
add_destructor<VariantDestruct<PackedByteArray>>();
add_destructor<VariantDestruct<PackedInt32Array>>();
add_destructor<VariantDestruct<PackedInt64Array>>();
add_destructor<VariantDestruct<PackedFloat32Array>>();
add_destructor<VariantDestruct<PackedFloat64Array>>();
add_destructor<VariantDestruct<PackedStringArray>>();
add_destructor<VariantDestruct<PackedVector2Array>>();
add_destructor<VariantDestruct<PackedVector3Array>>();
add_destructor<VariantDestruct<PackedColorArray>>();
}
void Variant::_unregister_variant_destructors() {
// Nothing to be done.
}
Variant::PTRDestructor Variant::get_ptr_destructor(Variant::Type p_type) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
return destruct_pointers[p_type];
}
bool Variant::has_destructor(Variant::Type p_type) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
return destruct_pointers[p_type] != nullptr;
}

View file

@ -0,0 +1,76 @@
/*************************************************************************/
/* variant_destruct.h */
/*************************************************************************/
/* 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. */
/*************************************************************************/
#ifndef VARIANT_DESTRUCT_H
#define VARIANT_DESTRUCT_H
#include "core/variant/variant.h"
#include "core/object/class_db.h"
template <class T>
struct VariantDestruct {};
#define MAKE_PTRDESTRUCT(m_type) \
template <> \
struct VariantDestruct<m_type> { \
_FORCE_INLINE_ static void ptr_destruct(void *p_ptr) { \
reinterpret_cast<m_type *>(p_ptr)->~m_type(); \
} \
_FORCE_INLINE_ static Variant::Type get_base_type() { \
return GetTypeInfo<m_type>::VARIANT_TYPE; \
} \
}
MAKE_PTRDESTRUCT(String);
MAKE_PTRDESTRUCT(Transform2D);
MAKE_PTRDESTRUCT(AABB);
MAKE_PTRDESTRUCT(Basis);
MAKE_PTRDESTRUCT(Transform3D);
MAKE_PTRDESTRUCT(StringName);
MAKE_PTRDESTRUCT(NodePath);
MAKE_PTRDESTRUCT(RID);
MAKE_PTRDESTRUCT(Callable);
MAKE_PTRDESTRUCT(Signal);
MAKE_PTRDESTRUCT(Dictionary);
MAKE_PTRDESTRUCT(Array);
MAKE_PTRDESTRUCT(PackedByteArray);
MAKE_PTRDESTRUCT(PackedInt32Array);
MAKE_PTRDESTRUCT(PackedInt64Array);
MAKE_PTRDESTRUCT(PackedFloat32Array);
MAKE_PTRDESTRUCT(PackedFloat64Array);
MAKE_PTRDESTRUCT(PackedStringArray);
MAKE_PTRDESTRUCT(PackedVector2Array);
MAKE_PTRDESTRUCT(PackedVector3Array);
MAKE_PTRDESTRUCT(PackedColorArray);
#undef MAKE_PTRDESTRUCT
#endif // VARIANT_DESTRUCT_H

View file

@ -1171,6 +1171,11 @@ struct VariantInitializer<PackedColorArray> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_color_array(v); }
};
template <>
struct VariantInitializer<Object *> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::object_assign_null(v); }
};
template <class T>
struct VariantZeroAssigner {
};
@ -1385,4 +1390,19 @@ struct VariantTypeAdjust<Object *> {
}
};
// GDNative extension helpers.
template <class T>
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 type_from_variant(void *p_value, void *p_variant) {
*((T *)p_value) = VariantInternalAccessor<T>::get(reinterpret_cast<Variant *>(p_variant));
}
};
#endif // VARIANT_INTERNAL_H

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="NativeExtension" inherits="RefCounted" version="4.0">
<class name="NativeExtension" inherits="Resource" version="4.0">
<brief_description>
</brief_description>
<description>