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",
"void *", "IntPtr", "value"
"GCHandle->MonoObject *", "IntPtr", "value"
) {
WrappedManagedFunction = "ConvertSmartEnumToNSString",
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",
"MonoReflectionType *", "IntPtr", "type"
"GCHandle->MonoReflectionType *", "IntPtr", "type"
) {
WrappedManagedFunction = "ConvertNSStringToSmartEnum",
OnlyDynamicUsage = true,

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

@ -1400,9 +1400,7 @@ xamarin_smart_enum_to_nsstring (MonoObject *value, void *context /* token ref */
guint32 context_ref = GPOINTER_TO_UINT (context);
if (context_ref == INVALID_TOKEN_REF) {
// 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 (GINT_TO_POINTER (handle), exception_gchandle);
mono_gchandle_free (handle);
NSString *rv = xamarin_convert_smart_enum_to_nsstring (value, exception_gchandle);
return rv;
} else {
// 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)
{
guint32 context_ref = GPOINTER_TO_UINT (context);
uint32_t gc_handle = 0;
MonoObject *obj;
if (context_ref == INVALID_TOKEN_REF) {
// 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)
return ptr;
gc_handle = GPOINTER_TO_UINT (rv);
obj = mono_gchandle_get_target (gc_handle);
} else {
// 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.
@ -1471,8 +1466,6 @@ xamarin_nsstring_to_smart_enum (id value, void *ptr, MonoClass *managedType, voi
ptr = xamarin_calloc (size);
void *value_ptr = mono_object_unbox (obj);
memcpy (ptr, value_ptr, size);
if (context_ref == INVALID_TOKEN_REF)
mono_gchandle_free (gc_handle);
return ptr;
}

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

@ -363,7 +363,7 @@ namespace ObjCRuntime {
// returns: a handle to a native NSString *
static IntPtr ConvertSmartEnumToNSString (IntPtr value_handle)
{
var value = GCHandle.FromIntPtr (value_handle).Target;
var value = GetGCHandleTarget (value_handle);
var smart_type = value.GetType ();
MethodBase getConstantMethod, 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.
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);
MethodBase getConstantMethod, 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.");
var rv = ((MethodInfo) getValueMethod).Invoke (null, new object [] { str });
return GCHandle.ToIntPtr (GCHandle.Alloc (rv));
return AllocGCHandle (rv);
}
#region Wrappers for delegate callbacks