Convert Runtime.ConvertNSStringToSmartEnum and Runtime.ConvertSmartEnumToNSString to use GCHandle.

These methods were already partially using GCHandles, so convert the parameter
using ObjectWrapper to GCHandle, and port the rest of the existing logic to
use the new helper API.
This commit is contained in:
Rolf Bjarne Kvinge 2020-05-04 11:08:44 +02:00
Родитель b360263f2c
Коммит b0974e8317
3 изменённых файлов: 8 добавлений и 15 удалений

Просмотреть файл

@ -264,15 +264,15 @@
}, },
new XDelegate ("NSString *", "IntPtr", "xamarin_convert_smart_enum_to_nsstring", new XDelegate ("NSString *", "IntPtr", "xamarin_convert_smart_enum_to_nsstring",
"void *", "IntPtr", "value" "GCHandle->MonoObject *", "IntPtr", "value"
) { ) {
WrappedManagedFunction = "ConvertSmartEnumToNSString", WrappedManagedFunction = "ConvertSmartEnumToNSString",
OnlyDynamicUsage = true, OnlyDynamicUsage = true,
}, },
new XDelegate ("void *", "IntPtr", "xamarin_convert_nsstring_to_smart_enum", new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_convert_nsstring_to_smart_enum",
"NSString *", "IntPtr", "value", "NSString *", "IntPtr", "value",
"MonoReflectionType *", "IntPtr", "type" "GCHandle->MonoReflectionType *", "IntPtr", "type"
) { ) {
WrappedManagedFunction = "ConvertNSStringToSmartEnum", WrappedManagedFunction = "ConvertNSStringToSmartEnum",
OnlyDynamicUsage = true, OnlyDynamicUsage = true,

Просмотреть файл

@ -1400,9 +1400,7 @@ xamarin_smart_enum_to_nsstring (MonoObject *value, void *context /* token ref */
guint32 context_ref = GPOINTER_TO_UINT (context); guint32 context_ref = GPOINTER_TO_UINT (context);
if (context_ref == INVALID_TOKEN_REF) { if (context_ref == INVALID_TOKEN_REF) {
// This requires the dynamic registrar to invoke the correct conversion function // This requires the dynamic registrar to invoke the correct conversion function
uint32_t handle = mono_gchandle_new (value, FALSE); NSString *rv = xamarin_convert_smart_enum_to_nsstring (value, exception_gchandle);
NSString *rv = xamarin_convert_smart_enum_to_nsstring (GINT_TO_POINTER (handle), exception_gchandle);
mono_gchandle_free (handle);
return rv; return rv;
} else { } else {
// The static registrar found the correct conversion function, and provided a token ref we can use // The static registrar found the correct conversion function, and provided a token ref we can use
@ -1435,16 +1433,13 @@ void *
xamarin_nsstring_to_smart_enum (id value, void *ptr, MonoClass *managedType, void *context, guint32 *exception_gchandle) xamarin_nsstring_to_smart_enum (id value, void *ptr, MonoClass *managedType, void *context, guint32 *exception_gchandle)
{ {
guint32 context_ref = GPOINTER_TO_UINT (context); guint32 context_ref = GPOINTER_TO_UINT (context);
uint32_t gc_handle = 0;
MonoObject *obj; MonoObject *obj;
if (context_ref == INVALID_TOKEN_REF) { if (context_ref == INVALID_TOKEN_REF) {
// This requires the dynamic registrar to invoke the correct conversion function // This requires the dynamic registrar to invoke the correct conversion function
void *rv = xamarin_convert_nsstring_to_smart_enum (value, mono_type_get_object (mono_domain_get (), mono_class_get_type (managedType)), exception_gchandle); obj = xamarin_convert_nsstring_to_smart_enum (value, mono_type_get_object (mono_domain_get (), mono_class_get_type (managedType)), exception_gchandle);
if (*exception_gchandle != 0) if (*exception_gchandle != 0)
return ptr; return ptr;
gc_handle = GPOINTER_TO_UINT (rv);
obj = mono_gchandle_get_target (gc_handle);
} else { } else {
// The static registrar found the correct conversion function, and provided a token ref we can use // The static registrar found the correct conversion function, and provided a token ref we can use
// to find it (and invoke it), without needing the dynamic registrar. // to find it (and invoke it), without needing the dynamic registrar.
@ -1471,8 +1466,6 @@ xamarin_nsstring_to_smart_enum (id value, void *ptr, MonoClass *managedType, voi
ptr = xamarin_calloc (size); ptr = xamarin_calloc (size);
void *value_ptr = mono_object_unbox (obj); void *value_ptr = mono_object_unbox (obj);
memcpy (ptr, value_ptr, size); memcpy (ptr, value_ptr, size);
if (context_ref == INVALID_TOKEN_REF)
mono_gchandle_free (gc_handle);
return ptr; return ptr;
} }

Просмотреть файл

@ -363,7 +363,7 @@ namespace ObjCRuntime {
// returns: a handle to a native NSString * // returns: a handle to a native NSString *
static IntPtr ConvertSmartEnumToNSString (IntPtr value_handle) static IntPtr ConvertSmartEnumToNSString (IntPtr value_handle)
{ {
var value = GCHandle.FromIntPtr (value_handle).Target; var value = GetGCHandleTarget (value_handle);
var smart_type = value.GetType (); var smart_type = value.GetType ();
MethodBase getConstantMethod, getValueMethod; MethodBase getConstantMethod, getValueMethod;
if (!Registrar.IsSmartEnum (smart_type, out getConstantMethod, out getValueMethod)) if (!Registrar.IsSmartEnum (smart_type, out getConstantMethod, out getValueMethod))
@ -380,13 +380,13 @@ namespace ObjCRuntime {
// returns: GCHandle to a (smart) enum value. Caller must free the GCHandle. // returns: GCHandle to a (smart) enum value. Caller must free the GCHandle.
static IntPtr ConvertNSStringToSmartEnum (IntPtr value, IntPtr type) static IntPtr ConvertNSStringToSmartEnum (IntPtr value, IntPtr type)
{ {
var smart_type = (Type) ObjectWrapper.Convert (type); var smart_type = (Type) GetGCHandleTarget (type);
var str = GetNSObject<NSString> (value); var str = GetNSObject<NSString> (value);
MethodBase getConstantMethod, getValueMethod; MethodBase getConstantMethod, getValueMethod;
if (!Registrar.IsSmartEnum (smart_type, out getConstantMethod, out getValueMethod)) if (!Registrar.IsSmartEnum (smart_type, out getConstantMethod, out getValueMethod))
throw ErrorHelper.CreateError (8024, $"Could not find a valid extension type for the smart enum '{smart_type.FullName}'. Please file a bug at https://github.com/xamarin/xamarin-macios/issues/new."); throw ErrorHelper.CreateError (8024, $"Could not find a valid extension type for the smart enum '{smart_type.FullName}'. Please file a bug at https://github.com/xamarin/xamarin-macios/issues/new.");
var rv = ((MethodInfo) getValueMethod).Invoke (null, new object [] { str }); var rv = ((MethodInfo) getValueMethod).Invoke (null, new object [] { str });
return GCHandle.ToIntPtr (GCHandle.Alloc (rv)); return AllocGCHandle (rv);
} }
#region Wrappers for delegate callbacks #region Wrappers for delegate callbacks