2016-04-21 15:19:32 +03:00
/ * - * - Mode : C ; tab - width : 8 ; indent - tabs - mode : t ; c - basic - offset : 8 - * - * /
/ *
* Authors : Rolf Bjarne Kvinge
*
* Copyright ( C ) 2014 Xamarin Inc . ( www . xamarin . com )
*
* /
# include < stdio . h >
# include < objc / objc . h >
# include < objc / runtime . h >
# include < objc / message . h >
# include < Foundation / Foundation . h >
2017-07-03 20:18:02 +03:00
# include "frameworks.h"
# include < AVFoundation / AVFoundation . h >
# include < CoreGraphics / CoreGraphics . h >
# include < CoreLocation / CoreLocation . h >
# if HAVE_COREMEDIA
# include < CoreMedia / CoreMedia . h >
# endif
# if HAVE_MAPKIT
# include < MapKit / MapKit . h >
# endif
# include < SceneKit / SceneKit . h >
# if HAVE_COREANIMATION
# include < QuartzCore / QuartzCore . h >
# endif
# if HAVE_UIKIT
# include < UIKit / UIKit . h >
# endif
2016-04-21 15:19:32 +03:00
# include < pthread . h >
2016-05-12 12:36:36 +03:00
# include "product.h"
2016-04-21 15:19:32 +03:00
# include "delegates.h"
# include "xamarin/xamarin.h"
# include "slinked-list.h"
# include "trampolines-internal.h"
2016-02-15 21:02:14 +03:00
# include "runtime-internal.h"
2016-04-21 15:19:32 +03:00
// # define DEBUG_REF _COUNTING
2018-05-22 15:53:19 +03:00
static pthread_mutex _t refcount_mutex = PTHREAD_RECURSIVE _MUTEX _INITIALIZER ;
2016-04-21 15:19:32 +03:00
2019-05-06 17:19:56 +03:00
size_t
xamarin_get _primitive _size ( char type )
{
switch ( type ) {
case _C _ID : return sizeof ( id ) ;
case _C _CLASS : return sizeof ( Class ) ;
case _C _SEL : return sizeof ( SEL ) ;
case _C _CHR : return sizeof ( char ) ;
case _C _UCHR : return sizeof ( unsigned char ) ;
case _C _SHT : return sizeof ( short ) ;
case _C _USHT : return sizeof ( unsigned short ) ;
case _C _INT : return sizeof ( int ) ;
case _C _UINT : return sizeof ( unsigned int ) ;
case _C _LNG : return sizeof ( long ) ;
case _C _ULNG : return sizeof ( unsigned long ) ;
case _C _LNG _LNG : return sizeof ( long long ) ;
case _C _ULNG _LNG : return sizeof ( unsigned long long ) ;
case _C _FLT : return sizeof ( float ) ;
case _C _DBL : return sizeof ( double ) ;
case _C _BOOL : return sizeof ( BOOL ) ;
case _C _VOID : return 0 ;
case _C _PTR : return sizeof ( void * ) ;
case _C _CHARPTR : return sizeof ( char * ) ;
default :
return 0 ;
}
}
2019-04-26 12:16:23 +03:00
static void *
2021-02-11 10:18:38 +03:00
xamarin_marshal _return _value _impl ( MonoType * mtype , const char * type , MonoObject * retval , bool retain , MonoMethod * method , MethodDescription * desc , GCHandle * exception_gchandle )
2016-04-21 15:19:32 +03:00
{
2016-02-15 21:02:14 +03:00
// COOP : accesses managed memory : unsafe mode .
MONO_ASSERT _GC _UNSAFE ;
2016-04-21 15:19:32 +03:00
/ * Any changes in this method probably need to be reflected in the static registrar as well * /
switch ( type [ 0 ] ) {
case _C _CLASS :
case _C _SEL :
2018-01-22 23:16:41 +03:00
return xamarin_get _handle _for _inativeobject ( retval , exception_gchandle ) ;
2016-04-21 15:19:32 +03:00
case _C _PTR : {
MonoClass * klass = mono_class _from _mono _type ( mtype ) ;
if ( mono_class _is _delegate ( klass ) ) {
2018-09-06 17:20:23 +03:00
return xamarin_get _block _for _delegate ( method , retval , NULL , INVALID_TOKEN _REF , exception_gchandle ) ;
2016-04-21 15:19:32 +03:00
} else {
return * ( void * * ) mono_object _unbox ( retval ) ;
}
}
case _C _ID : {
MonoClass * r_klass = mono_object _get _class ( ( MonoObject * ) retval ) ;
2017-07-03 20:18:02 +03:00
2020-05-04 12:08:47 +03:00
if ( desc && desc -> bindas [ 0 ] . original_type _handle ! = INVALID_GCHANDLE ) {
MonoReflectionType * original_type = ( MonoReflectionType * ) xamarin_gchandle _get _target ( desc -> bindas [ 0 ] . original_type _handle ) ;
2021-04-27 15:59:03 +03:00
MonoType * original_tp = mono_reflection _type _get _type ( original_type ) ;
xamarin_mono _object _release ( & original_type ) ;
return xamarin_generate _conversion _to _native ( retval , mono_class _get _type ( r_klass ) , original_tp , method , ( void * ) INVALID_TOKEN _REF , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
} else if ( r_klass = = mono_get _string _class ( ) ) {
2019-03-19 20:31:10 +03:00
return xamarin_string _to _nsstring ( ( MonoString * ) retval , retain ) ;
2016-04-21 15:19:32 +03:00
} else if ( xamarin_is _class _array ( r_klass ) ) {
2019-04-22 18:45:10 +03:00
NSArray * rv = xamarin_managed _array _to _nsarray ( ( MonoArray * ) retval , NULL , r_klass , exception_gchandle ) ;
if ( retain && rv )
[ rv retain ] ;
return rv ;
2016-04-21 15:19:32 +03:00
} else if ( xamarin_is _class _nsobject ( r_klass ) ) {
2016-06-02 13:18:45 +03:00
id i = xamarin_get _handle ( retval , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2016-06-02 13:18:45 +03:00
return NULL ;
2016-04-21 15:19:32 +03:00
xamarin_framework _peer _lock ( ) ;
[ i retain ] ;
xamarin_framework _peer _unlock ( ) ;
if ( ! retain )
[ i autorelease ] ;
mt_dummy _use ( retval ) ;
return i ;
} else if ( xamarin_is _class _inativeobject ( r_klass ) ) {
2016-06-02 13:18:45 +03:00
return xamarin_get _handle _for _inativeobject ( retval , exception_gchandle ) ;
2016-04-21 15:19:32 +03:00
} else {
2018-10-04 16:43:55 +03:00
xamarin_assertion _message ( "Don't know how to marshal a return value of type '%s.%s'. Please file a bug with a test case at https://github.com/xamarin/xamarin-macios/issues/new\n" , mono_class _get _namespace ( r_klass ) , mono_class _get _name ( r_klass ) ) ;
2016-04-21 15:19:32 +03:00
}
}
case _C _CHARPTR :
return ( void * ) mono_string _to _utf8 ( ( MonoString * ) retval ) ;
case _C _VOID :
return ( void * ) 0 x0 ;
default :
return * ( void * * ) mono_object _unbox ( retval ) ;
}
}
2021-02-11 10:18:38 +03:00
static GCHandle
xamarin_get _exception _for _element _conversion _failure ( GCHandle inner_exception _gchandle , unsigned long index )
2019-04-22 18:45:10 +03:00
{
2021-02-11 10:18:38 +03:00
GCHandle exception_gchandle = INVALID_GCHANDLE ;
2019-11-05 19:00:14 +03:00
char * msg = xamarin_strdup _printf ( "Failed to marshal the value at index %lu." , index ) ;
2019-04-22 18:45:10 +03:00
exception_gchandle = xamarin_create _product _exception _with _inner _exception ( 8036 , inner_exception _gchandle , msg ) ;
xamarin_free ( msg ) ;
return exception_gchandle ;
}
2019-04-26 12:16:23 +03:00
2021-02-11 10:18:38 +03:00
static GCHandle
xamarin_get _exception _for _return _value ( int code , GCHandle inner_exception _gchandle , SEL sel , MonoMethod * method , MonoType * returnType )
2019-04-26 12:16:23 +03:00
{
2021-02-11 10:18:38 +03:00
GCHandle exception_gchandle = INVALID_GCHANDLE ;
2019-04-26 12:16:23 +03:00
char * to_name = xamarin_type _get _full _name ( returnType , & exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( exception_gchandle ! = INVALID_GCHANDLE )
2019-04-26 12:16:23 +03:00
return exception_gchandle ;
char * method_full _name = mono_method _full _name ( method , TRUE ) ;
char * msg = xamarin_strdup _printf ( "Unable to marshal the return value of type '%s' to Objective-C.\n"
"Additional information:\n"
"\tSelector: %s\n"
"\tMethod: %s\n" , to_name , sel_getName ( sel ) , method_full _name ) ;
exception_gchandle = xamarin_create _product _exception _with _inner _exception ( code , inner_exception _gchandle , msg ) ;
xamarin_free ( msg ) ;
xamarin_free ( to_name ) ;
xamarin_free ( method_full _name ) ;
return exception_gchandle ;
}
void *
2021-02-11 10:18:38 +03:00
xamarin_marshal _return _value ( SEL sel , MonoType * mtype , const char * type , MonoObject * retval , bool retain , MonoMethod * method , MethodDescription * desc , GCHandle * exception_gchandle )
2019-04-26 12:16:23 +03:00
{
void * rv ;
rv = xamarin_marshal _return _value _impl ( mtype , type , retval , retain , method , desc , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE ) {
2019-04-26 12:16:23 +03:00
* exception_gchandle = xamarin_get _exception _for _return _value ( 8033 , * exception_gchandle , sel , method , mtype ) ;
return NULL ;
}
return rv ;
}
2016-05-12 12:36:36 +03:00
static const char *
get_method _description ( Class cls , SEL sel )
{
Protocol * * protocols ;
unsigned int p_count ;
Class p_cls = cls ;
struct objc_method _description desc ;
while ( p_cls ) {
protocols = class_copyProtocolList ( p_cls , & p_count ) ;
for ( unsigned int i = 0 ; i < p_count ; i + + ) {
desc = protocol_getMethodDescription ( protocols [ i ] , sel , YES , ! class_isMetaClass ( p_cls ) ) ;
if ( desc . types ! = NULL ) {
free ( protocols ) ;
return desc . types ;
}
}
free ( protocols ) ;
p_cls = class_getSuperclass ( p_cls ) ;
}
Method method = class_getInstanceMethod ( cls , sel ) ;
if ( ! method )
return NULL ;
struct objc_method _description * m_desc ;
m_desc = method_getDescription ( method ) ;
return m_desc ? m_desc -> types : NULL ;
}
static int
count_until ( const char * desc , char start , char end )
{
// Counts the number of characters until a certain character is found : ' end '
// If the ' start ' character is found , nesting is assumed , and an additional
// ' end ' character must be found before the function returns .
int i = 1 ;
int sub = 0 ;
while ( * desc ) {
if ( start = = * desc ) {
sub + + ;
} else if ( end = = * desc ) {
sub - - ;
if ( sub = = 0 )
return i ;
}
i + + ;
// This is not multi - byte safe . . .
desc + + ;
}
fprintf ( stderr , PRODUCT ": Unexpected type encoding, did not find end character '%c' in '%s'." , end , desc ) ;
return i ;
}
static int
get_type _description _length ( const char * desc )
{
int length = 0 ;
// This function returns the length of the first encoded type string in desc .
switch ( desc [ 0 ] ) {
case _C _ID :
if ( desc [ 1 ] = = ' ? ' ) {
// Example : [ AVAssetImageGenerator generateCGImagesAsynchronouslyForTimes : completionHandler : ] = ' v16 @ 0 : 4 @ 8 @ ? 12 '
length = 2 ;
} else {
length = 1 ;
}
break ;
case _C _CLASS :
case _C _SEL :
case _C _CHR :
case _C _UCHR :
case _C _SHT :
case _C _USHT :
case _C _INT :
case _C _UINT :
case _C _LNG :
case _C _ULNG :
case _C _LNG _LNG :
case _C _ULNG _LNG :
case _C _FLT :
case _C _DBL :
case _C _BOOL :
case _C _VOID :
case _C _CHARPTR :
length = 1 ;
break ;
case _C _PTR :
length = 1 ;
// handle broken encoding where simd types don ' t show up at all
// Example : [ GKPath pathWithPoints : count : radius : cyclical : ] = ' @ 24 @ 0 : 4 ^ 8 L12f16c20 '
// Here we assume that we ' re pointing to a simd type if we find
// a number ( i . e . only get the size of what we ' re pointing to
// if the next character isn ' t a number ) .
if ( desc [ 1 ] < ' 0 ' || desc [ 1 ] > ' 9 ' )
length + = get_type _description _length ( desc + 1 ) ;
break ;
case _C _ARY _B :
length = count_until ( desc , _C _ARY _B , _C _ARY _E ) ;
break ;
case _C _UNION _B :
length = count_until ( desc , _C _UNION _B , _C _UNION _E ) ;
break ;
case _C _STRUCT _B :
length = count_until ( desc , _C _STRUCT _B , _C _STRUCT _E ) ;
break ;
// The following are from table 6 -2 here : https : // developer . apple . com / library / mac / # documentation / Cocoa / Conceptual / ObjCRuntimeGuide / Articles / ocrtTypeEncodings . html
case ' r ' : // _C _CONST
case ' n ' :
case ' N ' :
case ' o ' :
case ' O ' :
case ' R ' :
case ' V ' :
length = 1 + get_type _description _length ( desc + 1 ) ;
break ;
case _C _BFLD :
length = 1 ;
break ;
case _C _UNDEF :
2019-07-04 08:30:44 +03:00
// Example : [ NSView sortSubviewsUsingFunction : context : ] = ' ^ ? 16 ^ v24 '
length = 1 ;
break ;
2016-05-12 12:36:36 +03:00
case _C _ATOM :
case _C _VECTOR :
xamarin_assertion _message ( "Unhandled type encoding: %s" , desc ) ;
break ;
default :
xamarin_assertion _message ( "Unsupported type encoding: %s" , desc ) ;
break ;
}
// Every type encoding _may _ be followed by the stack frame offset for that type
while ( desc [ length ] >= ' 0 ' && desc [ length ] <= ' 9 ' )
length + + ;
return length ;
}
2019-05-06 17:19:56 +03:00
// The input string will be freed ( so that the caller can use xamarin_strdup _printf easily ) .
2021-02-11 10:18:38 +03:00
GCHandle
2019-05-06 17:19:56 +03:00
xamarin_create _mt _exception ( char * msg )
{
MonoException * ex = xamarin_create _exception ( msg ) ;
xamarin_free ( msg ) ;
2021-02-11 10:18:38 +03:00
return xamarin_gchandle _new ( ( MonoObject * ) ex , FALSE ) ;
2019-05-06 17:19:56 +03:00
}
2019-05-07 08:35:39 +03:00
// Skips any brace and the content within . Supports nested braced content .
// Example :
// { bc } d = > d
// { a { b } cd } e = > e
static const char *
skip_nested _brace ( const char * type )
{
if ( * type ! = ' { ' )
return type ;
while ( * + + type ) {
switch ( * type ) {
case ' { ' :
return skip_nested _brace ( type ) ;
case ' } ' :
return type + + ;
default :
type + + ;
break ;
}
}
return NULL ;
}
// Takes a struct type name and collapses it into just the types of the
// fields . The purpose of this function is to get a string where each
// character represents the type + size of a field in the struct .
//
// Examples :
// { MKCoordinateRegion = { CLLocationCoordinate2D = dd } { MKCoordinateSpan = dd } } = > dddd
// { CGRect = dddd } = > dddd
// ^ q = > ^
// @ ? = > @ ( this is a block )
//
// type : the input type name
// struct_name : where to write the collapsed struct name . Returns an empty string if the array isn ' t big enough .
// max_char : the maximum number of characters to write to struct_name
// return value : false if something went wrong ( an exception thrown , or struct_name wasn ' t big enough ) .
bool
2021-02-11 10:18:38 +03:00
xamarin_collapse _struct _name ( const char * type , char struct_name [ ] , int max_char , GCHandle * exception_gchandle )
2019-05-07 08:35:39 +03:00
{
const char * input = type ;
int c = 0 ;
struct_name [ 0 ] = 0 ;
while ( * type ) {
switch ( * type ) {
case _C _STRUCT _B :
// Skip until ' = '
while ( type [ 1 ] ! = 0 && type [ 0 ] ! = ' = ' )
type + + ;
break ;
case _C _CONST :
case _C _STRUCT _E :
// don ' t care about these
break ;
case _C _PTR :
if ( c = = max_char ) {
LOGZ ( " xamarin_collapse_struct_name (%s, %i) => failed!\n" , input , max_char ) ;
struct_name [ 0 ] = 0 ; // return an empty string
return false ;
}
struct_name [ c + + ] = * type ;
type + + ;
// this might be a pointer to a pointer to a pointer to a labrador !
while ( * type = = _C _PTR )
type + + ;
// it might be a pointer to some nested stuff . skip that .
if ( * type = = ' { ' )
type = skip_nested _brace ( type ) ;
else
type + + ;
continue ;
case _C _ID :
case _C _CLASS :
case _C _SEL :
case _C _CHR :
case _C _UCHR :
case _C _SHT :
case _C _USHT :
case _C _INT :
case _C _UINT :
case _C _LNG :
case _C _ULNG :
case _C _LNG _LNG :
case _C _ULNG _LNG :
case _C _FLT :
case _C _DBL :
case _C _BOOL :
case _C _CHARPTR :
if ( c = = max_char ) {
LOGZ ( " xamarin_collapse_struct_name (%s, %i) => failed!\n" , input , max_char ) ;
struct_name [ 0 ] = 0 ; // return an empty string
return false ;
}
struct_name [ c + + ] = * type ;
break ;
case _C _UNDEF :
// unknown . this could be a block in which case the previous character is a ' @ ' .
break ;
case _C _ATOM :
case _C _ARY _B :
case _C _ARY _E :
case _C _UNION _B :
case _C _UNION _E :
case _C _VOID :
case _C _BFLD :
default :
// don ' t understand .
struct_name [ 0 ] = 0 ; // return an empty string
* exception_gchandle = xamarin_create _mt _exception ( xamarin_strdup _printf ( PRODUCT ": Cannot marshal type %s (unexpected type encoding: %c)\n" , input , * type ) ) ;
return false ;
}
type + + ;
}
2019-12-11 21:31:15 +03:00
if ( c = = max_char ) {
LOGZ ( " xamarin_collapse_struct_name (%s, %i) => failed (too long)!\n" , input , max_char ) ;
struct_name [ 0 ] = 0 ; // return an empty string
return false ;
}
2019-05-07 08:35:39 +03:00
struct_name [ c ] = 0 ; // Zero - terminate .
LOGZ ( " xamarin_collapse_struct_name (%s, %i) => %s (succeeded)\n" , input , max_char , struct_name ) ;
return true ;
}
2019-12-12 06:17:29 +03:00
int
2016-04-21 15:19:32 +03:00
xamarin_get _frame _length ( id self , SEL sel )
{
2016-05-12 12:36:36 +03:00
if ( self = = NULL )
return sizeof ( void * ) * 3 ; // we might be in objc_msgStret , in which case we ' ll need to copy three arguments .
// [ NSDecimalNumber initWithDecimal : ] has this descriptor : "@36@0:8{?=b8b4b1b1b18[8S]}16"
// which NSMethodSignature chokes on : NSInvalidArgumentException Reason : + [ NSMethodSignature signatureWithObjCTypes : ] : unsupported type encoding spec ' { ? } '
// So instead parse the description ourselves .
2019-11-05 19:00:14 +03:00
unsigned long length = 0 ;
2019-06-14 20:07:42 +03:00
[ self class ] ; // There ' s a bug in the ObjC runtime where we might get an uninitialized Class instance from object_getClass . See #6258 . Calling the ' class ' selector first makes sure the Class instance is initialized .
2016-05-12 12:36:36 +03:00
Class cls = object_getClass ( self ) ;
const char * method_description = get_method _description ( cls , sel ) ;
const char * desc = method_description ;
if ( desc = = NULL ) {
// This happens with [ [ UITableViewCell appearance ] backgroundColor ]
@ try {
NSMethodSignature * sig = [ self methodSignatureForSelector : sel ] ;
length = [ sig frameLength ] ;
} @ catch ( NSException * ex ) {
length = sizeof ( void * ) * 64 ; // some high - ish number .
2019-11-05 19:00:14 +03:00
fprintf ( stderr , PRODUCT ": Failed to calculate the frame size for the method [%s %s] (%s). Using a value of %lu instead.\n" , class_getName ( cls ) , sel_getName ( sel ) , [ [ ex description ] UTF8String ] , length ) ;
2016-05-12 12:36:36 +03:00
}
} else {
// The format of the method type encoding is described here : http : // stackoverflow . com / a / 11492151 / 183422
// the return type might have a number after it , which is the size of the argument frame
// first get this number ( if it ' s there ) , and use it as a minimum value for the frame length
int rvlength = get_type _description _length ( desc ) ;
2019-11-05 19:00:14 +03:00
unsigned long min_length = 0 ;
2016-05-12 12:36:36 +03:00
if ( rvlength > 0 ) {
const char * min_start = desc + rvlength ;
// the number is at the end of the return type encoding , so find any numbers
// at the end of the type encoding .
while ( min_start > desc && min_start [ -1 ] >= ' 0 ' && min_start [ -1 ] <= ' 9 ' )
min_start - - ;
if ( min_start < desc + rvlength ) {
for ( int i = 0 ; i < desc + rvlength - min_start ; i + + )
2019-11-15 18:39:38 +03:00
min_length = min_length * 10 ul + ( unsigned long ) ( min_start [ i ] - ' 0 ' ) ;
2016-05-12 12:36:36 +03:00
}
}
// fprintf ( stderr , "Found desc '%s' for [%s %s] with min frame length %i\n" , desc , class_getName ( cls ) , sel_getName ( sel ) , min_length ) ;
// skip the return value .
desc + = rvlength ;
while ( * desc ) {
2019-10-30 22:58:13 +03:00
unsigned long tl = xamarin_objc _type _size ( desc ) ;
2016-05-12 12:36:36 +03:00
// round up to pointer size
if ( tl % sizeof ( void * ) ! = 0 )
tl + = sizeof ( void * ) - ( tl % sizeof ( void * ) ) ;
length + = tl ;
// fprintf ( stderr , " argument=%s length=%i totallength=%i\n" , desc , tl , length ) ;
desc + = get_type _description _length ( desc ) ;
}
if ( min_length > length ) {
// this might happen for methods that take simd types , since those arguments don ' t show up in the
// method signature encoding at all , but they ' re still added to the frame size .
// fprintf ( stderr , " min length: %i is higher than calculated length: %i for [%s %s] with description %s\n" , min_length , length , class_getName ( cls ) , sel_getName ( sel ) , method_description ) ;
length = min_length ;
}
}
// we can ' t detect varargs , so just add 16 more pointer sized arguments to be on the safe - ish side .
length + = sizeof ( void * ) * 16 ;
2016-04-21 15:19:32 +03:00
2019-12-12 06:17:29 +03:00
return ( int ) length ;
2016-04-21 15:19:32 +03:00
}
static inline void
find_objc _method _implementation ( struct objc_super * sup , id self , SEL sel , IMP xamarin_impl )
{
2016-02-15 21:02:14 +03:00
// COOP : does not access managed memory : any mode
2016-04-21 15:19:32 +03:00
Class klass = object_getClass ( self ) ;
Class sklass = class_getSuperclass ( klass ) ;
IMP imp = class_getMethodImplementation ( klass , sel ) ;
IMP simp = class_getMethodImplementation ( sklass , sel ) ;
while ( imp = = simp || simp = = xamarin_impl ) {
sklass = class_getSuperclass ( sklass ) ;
simp = class_getMethodImplementation ( sklass , sel ) ;
}
sup -> receiver = self ;
# if ! defined ( __cplusplus ) && ! __OBJC2 __
sup -> class = sklass ;
# else
sup -> super_class = sklass ;
# endif
}
id
xamarin_invoke _objc _method _implementation ( id self , SEL sel , IMP xamarin_impl )
{
2016-02-15 21:02:14 +03:00
// COOP : does not access managed memory : any mode
2016-04-21 15:19:32 +03:00
struct objc_super sup ;
find_objc _method _implementation ( & sup , self , sel , xamarin_impl ) ;
2019-08-28 18:05:38 +03:00
typedef id ( * func_objc _msgSendSuper ) ( struct objc_super * sup , SEL sel ) ;
return ( ( func_objc _msgSendSuper ) objc_msgSendSuper ) ( & sup , sel ) ;
2016-04-21 15:19:32 +03:00
}
# if MONOMAC
id
xamarin_copyWithZone _trampoline1 ( id self , SEL sel , NSZone * zone )
{
2016-02-15 21:02:14 +03:00
// COOP : does not access managed memory : any mode
2016-04-21 15:19:32 +03:00
// This is for subclasses that themselves do not implement Copy ( NSZone )
id rv ;
2021-02-11 10:18:38 +03:00
GCHandle gchandle ;
enum XamarinGCHandleFlags flags = XamarinGCHandleFlags_None ;
2016-04-21 15:19:32 +03:00
struct objc_super sup ;
# if defined ( DEBUG_REF _COUNTING )
2016-09-06 23:55:23 +03:00
PRINT ( "xamarin_copyWithZone_trampoline1 (%p, %s, %p)\n" , self , sel_getName ( sel ) , zone ) ;
2016-04-21 15:19:32 +03:00
# endif
// Clear out our own GCHandle
2021-02-11 10:18:38 +03:00
gchandle = xamarin_get _gchandle _with _flags ( self , & flags ) ;
if ( gchandle ! = INVALID_GCHANDLE )
xamarin_set _gchandle _with _flags ( self , INVALID_GCHANDLE , XamarinGCHandleFlags_None ) ;
2016-04-21 15:19:32 +03:00
// Call the base class implementation
id (*invoke) (struct objc_super *, SEL, NSZone*) = ( id (*)(struct objc_super *, SEL, NSZone*) ) objc_msgSendSuper ;
find_objc _method _implementation ( & sup , self , sel , ( IMP ) xamarin_copyWithZone _trampoline1 ) ;
rv = invoke ( & sup , sel , zone ) ;
// Restore our GCHandle
2021-02-11 10:18:38 +03:00
if ( gchandle ! = INVALID_GCHANDLE )
xamarin_set _gchandle _with _flags ( self , gchandle , flags ) ;
2016-04-21 15:19:32 +03:00
return rv ;
}
id
xamarin_copyWithZone _trampoline2 ( id self , SEL sel , NSZone * zone )
{
2016-02-15 21:02:14 +03:00
// COOP : does not access managed memory : any mode
2016-04-21 15:19:32 +03:00
// This is for subclasses that already implement Copy ( NSZone )
id rv ;
2021-02-11 10:18:38 +03:00
GCHandle gchandle ;
enum XamarinGCHandleFlags flags = XamarinGCHandleFlags_None ;
2016-04-21 15:19:32 +03:00
# if defined ( DEBUG_REF _COUNTING )
2016-09-06 23:55:23 +03:00
PRINT ( "xamarin_copyWithZone_trampoline2 (%p, %s, %p)\n" , self , sel_getName ( sel ) , zone ) ;
2016-04-21 15:19:32 +03:00
# endif
// Clear out our own GCHandle
2021-02-11 10:18:38 +03:00
gchandle = xamarin_get _gchandle _with _flags ( self , & flags ) ;
if ( gchandle ! = INVALID_GCHANDLE )
xamarin_set _gchandle _with _flags ( self , INVALID_GCHANDLE , XamarinGCHandleFlags_None ) ;
2016-04-21 15:19:32 +03:00
// Call the managed implementation
id (*invoke) (id, SEL, NSZone*) = ( id (*)(id, SEL, NSZone*) ) xamarin_trampoline ;
rv = invoke ( self , sel , zone ) ;
// Restore our GCHandle
2021-02-11 10:18:38 +03:00
if ( gchandle ! = INVALID_GCHANDLE )
xamarin_set _gchandle _with _flags ( self , gchandle , flags ) ;
2016-04-21 15:19:32 +03:00
return rv ;
}
# endif
void
xamarin_release _trampoline ( id self , SEL sel )
{
2016-02-15 21:02:14 +03:00
// COOP : does not access managed memory : any mode , but it assumes safe mode upon entry ( it takes locks , and doesn ' t switch to safe mode ) .
[coop runtime] add a GC transition and relax some GC related assertions (#7036)
* [coop] add missing gc_unsafe transition
frame #3: 0x02a39fd4 monotouchtest`log_callback(log_domain=0x00000000, log_level="error", message="../../../../../mono/metadata/object.c:1905: Expected GC Unsafe mode but was in STATE_BLOCKING state", fatal=4, user_data=0x00000000) at runtime.m:1251:3
frame #4: 0x02a03f78 monotouchtest`monoeg_g_logv_nofree(log_domain=0x00000000, log_level=G_LOG_LEVEL_ERROR, format=<unavailable>, args=<unavailable>) at goutput.c:149:2 [opt]
frame #5: 0x02a03f14 monotouchtest`monoeg_g_logv(log_domain=<unavailable>, log_level=<unavailable>, format=<unavailable>, args=<unavailable>) at goutput.c:156:10 [opt]
frame #6: 0x02a03fa8 monotouchtest`monoeg_g_log(log_domain=<unavailable>, log_level=<unavailable>, format=<unavailable>) at goutput.c:165:2 [opt]
frame #7: 0x029e54f8 monotouchtest`assert_gc_unsafe_mode(file="../../../../../mono/metadata/object.c", lineno=1905) at checked-build.c:396:3 [opt]
frame #8: 0x0294ef98 monotouchtest`mono_class_vtable_checked(domain=0x16d87b70, klass=0x17bfab98, error=0x19498a08) at object.c:1905:2 [opt]
frame #9: 0x0298f0dc monotouchtest`get_current_thread_ptr_for_domain(domain=0x16d87b70, thread=0x03f645d0) at threads.c:635:2 [opt]
frame #10: 0x0298d9dc monotouchtest`mono_thread_current at threads.c:2026:23 [opt]
frame #11: 0x02992a80 monotouchtest`mono_runtime_set_pending_exception(exc=0x0357e4a0, overwrite=0) at threads.c:5176:23 [opt]
frame #12: 0x02a3c650 monotouchtest`::xamarin_process_nsexception_using_mode(ns_exception=name: "System.ApplicationException" - reason: "3,14", throwManagedAsDefault=false) at runtime.m:2369:4
frame #13: 0x02a3c478 monotouchtest`::xamarin_process_nsexception(ns_exception=name: "System.ApplicationException" - reason: "3,14") at runtime.m:2336:2
frame #14: 0x0270b488 monotouchtest`::xamarin_pinvoke_wrapper_objc_msgSendSuper18(__p__0=0x0357d0f0, __p__1=0x02ad1ef2) at pinvokes.m:5732:4
frame #15: 0x02a64764 monotouchtest`do_icall(frame=<unavailable>, sig=0x17d70bf0, op=<unavailable>, sp=0x19498fa0, ptr=<unavailable>, save_last_error=0) at interp.c:1947:3 [opt]
frame #16: 0x02a632b8 monotouchtest`do_icall_wrapper(frame=0x194991b0, sig=0x17d70bf0, op=547, sp=0x19498fb0, ptr=0x0270b408, save_last_error=0) at interp.c:2037:7 [opt]
Messaging::void_objc_msgSendSuper @ 396160394 "calli.nat.fast" || frame #17: 0x02a51d5c monotouchtest`interp_exec_method_full(frame=0x194991b0, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3229:9 [opt]
ObjCExceptionTest::InvokeManagedExceptionThrower @ 396160296 "vcall" || frame #18: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x19499370, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3400:4 [opt]
ExceptionsTest::ManagedExceptionPassthrough @ 396150902 "vcallvirt.fast" || frame #19: 0x02a521cc monotouchtest`interp_exec_method_full(frame=0x194994d0, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3325:4 [opt]
Object::runtime_invoke_direct_void__this__ @ 401347822 "vcall" || frame #20: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x19499588, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3400:4 [opt]
frame #21: 0x02a506f8 monotouchtest`interp_runtime_invoke(method=<unavailable>, obj=0x0357c4f0, params=0x00000000, exc=0x1949965c, error=0x194998b8) at interp.c:1766:2 [opt]
frame #22: 0x028a739c monotouchtest`mono_jit_runtime_invoke(method=0x17534858, obj=<unavailable>, params=0x00000000, exc=<unavailable>, error=0x194998b8) at mini-runtime.c:3170:12 [opt]
frame #23: 0x02951cfc monotouchtest`do_runtime_invoke(method=0x17534858, obj=0x0357c4f0, params=0x00000000, exc=0x00000000, error=0x194998b8) at object.c:3017:11 [opt]
frame #24: 0x0294e6d4 monotouchtest`mono_runtime_invoke_checked(method=<unavailable>, obj=<unavailable>, params=<unavailable>, error=<unavailable>) at class-getters.h:24:1 [opt] [artificial]
frame #25: 0x02955408 monotouchtest`mono_runtime_try_invoke_array(method=0x17534858, obj=0x0357c4f0, params=0x00000000, exc=0x00000000, error=0x194998b8) at object.c:5564:10 [opt]
frame #26: 0x02905fac monotouchtest`ves_icall_InternalInvoke(method=<unavailable>, this_arg=<unavailable>, params=0x00000000, exc=0x19499f0c) at icall.c:3753:8 [opt]
frame #27: 0x02a64788 monotouchtest`do_icall(frame=<unavailable>, sig=0x17496978, op=<unavailable>, sp=0x19499d88, ptr=<unavailable>, save_last_error=0) at interp.c:1982:20 [opt]
frame #28: 0x02a632b8 monotouchtest`do_icall_wrapper(frame=0x19499fb0, sig=0x17496978, op=552, sp=0x19499da0, ptr=0x02905bec, save_last_error=0) at interp.c:2037:7 [opt]
RuntimeMethodInfo::InternalInvoke @ 400702536 "calli.nat.fast" || frame #29: 0x02a51d5c monotouchtest`interp_exec_method_full(frame=0x19499fb0, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3229:9 [opt]
RuntimeMethodInfo::Invoke @ 400701852 "call" || frame #30: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x1949a110, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3400:4 [opt]
MethodBase::Invoke @ 400700872 "callvirt.fast" || frame #31: 0x02a521cc monotouchtest`interp_exec_method_full(frame=0x1949a280, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3325:4 [opt]
* [coop] relax a couple GC state assertions
* [coop] update doc for enabling GC assertions
* [coop] relax a GC assertion in release trampoline
2019-09-23 23:08:25 +03:00
MONO_ASSERT _GC _SAFE _OR _DETACHED ;
2016-02-15 21:02:14 +03:00
2019-11-05 19:00:14 +03:00
unsigned long ref_count ;
2016-04-21 15:19:32 +03:00
bool detach = false ;
pthread_mutex _lock ( & refcount_mutex ) ;
ref_count = [ self retainCount ] ;
# if defined ( DEBUG_REF _COUNTING )
2016-09-06 23:55:23 +03:00
PRINT ( "xamarin_release_trampoline (%s Handle=%p) retainCount=%d; HasManagedRef=%i GCHandle=%i\n" ,
2016-04-21 15:19:32 +03:00
class_getName ( [ self class ] ) , self , ref_count , xamarin_has _managed _ref ( self ) , xamarin_get _gchandle ( self ) ) ;
# endif
/ *
* We need to decide if the gchandle should become a weak one .
* This happens if managed code will end up holding the only ref .
* /
2016-02-15 21:02:14 +03:00
if ( ref_count = = 2 && xamarin_has _managed _ref _safe ( self ) ) {
2016-04-21 15:19:32 +03:00
xamarin_switch _gchandle ( self , true / * weak * / ) ;
detach = true ;
}
pthread_mutex _unlock ( & refcount_mutex ) ;
/ * Invoke the real retain method * /
xamarin_invoke _objc _method _implementation ( self , sel , ( IMP ) xamarin_release _trampoline ) ;
if ( detach )
mono_thread _detach _if _exiting ( ) ;
}
void
2021-02-11 10:18:38 +03:00
xamarin_notify _dealloc ( id self , GCHandle gchandle )
2016-04-21 15:19:32 +03:00
{
2021-02-11 10:18:38 +03:00
GCHandle exception_gchandle = INVALID_GCHANDLE ;
2016-06-02 13:18:45 +03:00
2016-02-15 21:02:14 +03:00
// COOP : safe mode upon entry , switches to unsafe when acccessing managed memory .
2016-05-16 20:30:58 +03:00
MONO_ASSERT _GC _SAFE _OR _DETACHED ;
2016-02-15 21:02:14 +03:00
/ * This is needed because we call into managed code below ( xamarin_unregister _nsobject ) * /
MONO_THREAD _ATTACH ; // COOP : This will swith to GC_UNSAFE
2016-04-21 15:19:32 +03:00
/ * Object is about to die . Unregister it and free any gchandles we may have * /
# if defined ( DEBUG_REF _COUNTING )
2020-05-04 12:08:40 +03:00
PRINT ( "xamarin_notify_dealloc (%p, %i)\n" , self , gchandle ) ;
2016-04-21 15:19:32 +03:00
# endif
2020-05-04 12:08:40 +03:00
xamarin_unregister _nsobject ( self , GINT_TO _POINTER ( gchandle ) , & exception_gchandle ) ;
2016-04-21 15:19:32 +03:00
xamarin_free _gchandle ( self , gchandle ) ;
2016-02-15 21:02:14 +03:00
MONO_THREAD _DETACH ; // COOP : This will switch to GC_SAFE
2016-06-02 13:18:45 +03:00
xamarin_process _managed _exception _gchandle ( exception_gchandle ) ;
2016-04-21 15:19:32 +03:00
mono_thread _detach _if _exiting ( ) ;
}
id
xamarin_retain _trampoline ( id self , SEL sel )
{
2016-02-15 21:02:14 +03:00
// COOP : safe mode upon entry , switches to unsafe when acccessing managed memory .
[coop runtime] add a GC transition and relax some GC related assertions (#7036)
* [coop] add missing gc_unsafe transition
frame #3: 0x02a39fd4 monotouchtest`log_callback(log_domain=0x00000000, log_level="error", message="../../../../../mono/metadata/object.c:1905: Expected GC Unsafe mode but was in STATE_BLOCKING state", fatal=4, user_data=0x00000000) at runtime.m:1251:3
frame #4: 0x02a03f78 monotouchtest`monoeg_g_logv_nofree(log_domain=0x00000000, log_level=G_LOG_LEVEL_ERROR, format=<unavailable>, args=<unavailable>) at goutput.c:149:2 [opt]
frame #5: 0x02a03f14 monotouchtest`monoeg_g_logv(log_domain=<unavailable>, log_level=<unavailable>, format=<unavailable>, args=<unavailable>) at goutput.c:156:10 [opt]
frame #6: 0x02a03fa8 monotouchtest`monoeg_g_log(log_domain=<unavailable>, log_level=<unavailable>, format=<unavailable>) at goutput.c:165:2 [opt]
frame #7: 0x029e54f8 monotouchtest`assert_gc_unsafe_mode(file="../../../../../mono/metadata/object.c", lineno=1905) at checked-build.c:396:3 [opt]
frame #8: 0x0294ef98 monotouchtest`mono_class_vtable_checked(domain=0x16d87b70, klass=0x17bfab98, error=0x19498a08) at object.c:1905:2 [opt]
frame #9: 0x0298f0dc monotouchtest`get_current_thread_ptr_for_domain(domain=0x16d87b70, thread=0x03f645d0) at threads.c:635:2 [opt]
frame #10: 0x0298d9dc monotouchtest`mono_thread_current at threads.c:2026:23 [opt]
frame #11: 0x02992a80 monotouchtest`mono_runtime_set_pending_exception(exc=0x0357e4a0, overwrite=0) at threads.c:5176:23 [opt]
frame #12: 0x02a3c650 monotouchtest`::xamarin_process_nsexception_using_mode(ns_exception=name: "System.ApplicationException" - reason: "3,14", throwManagedAsDefault=false) at runtime.m:2369:4
frame #13: 0x02a3c478 monotouchtest`::xamarin_process_nsexception(ns_exception=name: "System.ApplicationException" - reason: "3,14") at runtime.m:2336:2
frame #14: 0x0270b488 monotouchtest`::xamarin_pinvoke_wrapper_objc_msgSendSuper18(__p__0=0x0357d0f0, __p__1=0x02ad1ef2) at pinvokes.m:5732:4
frame #15: 0x02a64764 monotouchtest`do_icall(frame=<unavailable>, sig=0x17d70bf0, op=<unavailable>, sp=0x19498fa0, ptr=<unavailable>, save_last_error=0) at interp.c:1947:3 [opt]
frame #16: 0x02a632b8 monotouchtest`do_icall_wrapper(frame=0x194991b0, sig=0x17d70bf0, op=547, sp=0x19498fb0, ptr=0x0270b408, save_last_error=0) at interp.c:2037:7 [opt]
Messaging::void_objc_msgSendSuper @ 396160394 "calli.nat.fast" || frame #17: 0x02a51d5c monotouchtest`interp_exec_method_full(frame=0x194991b0, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3229:9 [opt]
ObjCExceptionTest::InvokeManagedExceptionThrower @ 396160296 "vcall" || frame #18: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x19499370, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3400:4 [opt]
ExceptionsTest::ManagedExceptionPassthrough @ 396150902 "vcallvirt.fast" || frame #19: 0x02a521cc monotouchtest`interp_exec_method_full(frame=0x194994d0, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3325:4 [opt]
Object::runtime_invoke_direct_void__this__ @ 401347822 "vcall" || frame #20: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x19499588, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3400:4 [opt]
frame #21: 0x02a506f8 monotouchtest`interp_runtime_invoke(method=<unavailable>, obj=0x0357c4f0, params=0x00000000, exc=0x1949965c, error=0x194998b8) at interp.c:1766:2 [opt]
frame #22: 0x028a739c monotouchtest`mono_jit_runtime_invoke(method=0x17534858, obj=<unavailable>, params=0x00000000, exc=<unavailable>, error=0x194998b8) at mini-runtime.c:3170:12 [opt]
frame #23: 0x02951cfc monotouchtest`do_runtime_invoke(method=0x17534858, obj=0x0357c4f0, params=0x00000000, exc=0x00000000, error=0x194998b8) at object.c:3017:11 [opt]
frame #24: 0x0294e6d4 monotouchtest`mono_runtime_invoke_checked(method=<unavailable>, obj=<unavailable>, params=<unavailable>, error=<unavailable>) at class-getters.h:24:1 [opt] [artificial]
frame #25: 0x02955408 monotouchtest`mono_runtime_try_invoke_array(method=0x17534858, obj=0x0357c4f0, params=0x00000000, exc=0x00000000, error=0x194998b8) at object.c:5564:10 [opt]
frame #26: 0x02905fac monotouchtest`ves_icall_InternalInvoke(method=<unavailable>, this_arg=<unavailable>, params=0x00000000, exc=0x19499f0c) at icall.c:3753:8 [opt]
frame #27: 0x02a64788 monotouchtest`do_icall(frame=<unavailable>, sig=0x17496978, op=<unavailable>, sp=0x19499d88, ptr=<unavailable>, save_last_error=0) at interp.c:1982:20 [opt]
frame #28: 0x02a632b8 monotouchtest`do_icall_wrapper(frame=0x19499fb0, sig=0x17496978, op=552, sp=0x19499da0, ptr=0x02905bec, save_last_error=0) at interp.c:2037:7 [opt]
RuntimeMethodInfo::InternalInvoke @ 400702536 "calli.nat.fast" || frame #29: 0x02a51d5c monotouchtest`interp_exec_method_full(frame=0x19499fb0, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3229:9 [opt]
RuntimeMethodInfo::Invoke @ 400701852 "call" || frame #30: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x1949a110, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3400:4 [opt]
MethodBase::Invoke @ 400700872 "callvirt.fast" || frame #31: 0x02a521cc monotouchtest`interp_exec_method_full(frame=0x1949a280, context=<unavailable>, clause_args=<unavailable>, error=<unavailable>) at interp.c:3325:4 [opt]
* [coop] relax a couple GC state assertions
* [coop] update doc for enabling GC assertions
* [coop] relax a GC assertion in release trampoline
2019-09-23 23:08:25 +03:00
MONO_ASSERT _GC _SAFE _OR _DETACHED ;
2016-02-15 21:02:14 +03:00
2016-04-21 15:19:32 +03:00
pthread_mutex _lock ( & refcount_mutex ) ;
# if defined ( DEBUG_REF _COUNTING )
2021-02-11 10:18:38 +03:00
int ref_count = ( int ) [ self retainCount ] ;
2016-04-21 15:19:32 +03:00
bool had_managed _ref = xamarin_has _managed _ref ( self ) ;
2021-02-11 10:18:38 +03:00
GCHandle pre_gchandle = xamarin_get _gchandle ( self ) ;
2016-04-21 15:19:32 +03:00
# endif
/ *
* We need to make sure we have a strong GCHandle .
* We can not rely the retainCount changing from 1 to 2 , since
* we can not monitor all retains ( see bug #26532 ) .
* So just always make sure we have a strong GCHandle after a retain .
* /
xamarin_switch _gchandle ( self , false / * strong * / ) ;
pthread_mutex _unlock ( & refcount_mutex ) ;
/ * Invoke the real retain method * /
self = xamarin_invoke _objc _method _implementation ( self , sel , ( IMP ) xamarin_retain _trampoline ) ;
# if defined ( DEBUG_REF _COUNTING )
2016-09-06 23:55:23 +03:00
PRINT ( "xamarin_retain_trampoline (%s Handle=%p) initial retainCount=%d; new retainCount=%d HadManagedRef=%i HasManagedRef=%i old GCHandle=%i new GCHandle=%i\n" ,
2016-04-21 15:19:32 +03:00
class_getName ( [ self class ] ) , self , ref_count , ( int ) [ self retainCount ] , had_managed _ref , xamarin_has _managed _ref ( self ) , pre_gchandle , xamarin_get _gchandle ( self ) ) ;
# endif
return self ;
}
// We try to use the associated object API as little as possible , because the API does
// not like recursion ( see bug #35017 ) , and it calls retain / release , which we might
// have overridden with our own code that calls these functions . So in addition to
// keeping the gchandle inside the associated object , we also keep it in a hash
// table , so that xamarin_get _gchandle _trampoline does not have to call any
// associated object API to get the gchandle .
static CFMutableDictionaryRef gchandle_hash = NULL ;
static pthread_mutex _t gchandle_hash _lock = PTHREAD_MUTEX _INITIALIZER ;
2021-02-11 10:18:38 +03:00
struct gchandle_dictionary _entry {
GCHandle gc_handle ;
enum XamarinGCHandleFlags flags ;
} ;
static void
release_gchandle _dictionary _entry ( CFAllocatorRef allocator , const void * value )
{
free ( ( void * ) value ) ;
}
2016-04-21 15:19:32 +03:00
static const char * associated_key = "x" ; // the string value doesn ' t matter , only the pointer value .
2021-04-23 19:42:11 +03:00
bool
2021-02-11 10:18:38 +03:00
xamarin_set _gchandle _trampoline ( id self , SEL sel , GCHandle gc_handle , enum XamarinGCHandleFlags flags )
2016-04-21 15:19:32 +03:00
{
2021-02-11 10:18:38 +03:00
// COOP : Called by ObjC ( when the setGCHandle : flags : selector is called on an object ) .
2016-02-15 21:02:14 +03:00
// COOP : Safe mode upon entry , and doesn ' t access managed memory , so no need to change .
MONO_ASSERT _GC _SAFE ;
2016-04-21 15:19:32 +03:00
/ * This is for types registered using the dynamic registrar * /
XamarinAssociatedObject * obj ;
obj = objc_getAssociatedObject ( self , associated_key ) ;
2021-04-23 19:42:11 +03:00
// Check if we ' re setting the initial value , in which case we don ' t want to overwrite
if ( obj ! = NULL && obj -> gc_handle ! = INVALID_GCHANDLE && ( ( flags & XamarinGCHandleFlags_InitialSet ) = = XamarinGCHandleFlags_InitialSet ) )
return false ;
flags = ( enum XamarinGCHandleFlags ) ( flags & ~ XamarinGCHandleFlags_InitialSet ) ; // Remove the InitialSet flag , we don ' t want to store it .
2021-02-11 10:18:38 +03:00
if ( obj = = NULL && gc_handle ! = INVALID_GCHANDLE ) {
2016-04-21 15:19:32 +03:00
obj = [ [ XamarinAssociatedObject alloc ] init ] ;
obj -> gc_handle = gc_handle ;
2021-02-11 10:18:38 +03:00
obj -> flags = flags ;
2016-04-21 15:19:32 +03:00
obj -> native_object = self ;
objc_setAssociatedObject ( self , associated_key , obj , OBJC_ASSOCIATION _RETAIN _NONATOMIC ) ;
[ obj release ] ;
}
2021-02-11 10:18:38 +03:00
if ( obj ! = NULL ) {
2016-04-21 15:19:32 +03:00
obj -> gc_handle = gc_handle ;
2021-02-11 10:18:38 +03:00
obj -> flags = flags ;
}
2016-04-21 15:19:32 +03:00
pthread_mutex _lock ( & gchandle_hash _lock ) ;
2021-02-11 10:18:38 +03:00
if ( gchandle_hash = = NULL ) {
CFDictionaryValueCallBacks value_callbacks ;
value_callbacks . release = release_gchandle _dictionary _entry ;
2016-04-21 15:19:32 +03:00
gchandle_hash = CFDictionaryCreateMutable ( kCFAllocatorDefault , 0 , NULL , NULL ) ;
2021-02-11 10:18:38 +03:00
}
if ( gc_handle = = INVALID_GCHANDLE ) {
2016-04-21 15:19:32 +03:00
CFDictionaryRemoveValue ( gchandle_hash , self ) ;
} else {
2021-02-11 10:18:38 +03:00
struct gchandle_dictionary _entry * entry = ( struct gchandle_dictionary _entry * ) malloc ( sizeof ( struct gchandle_dictionary _entry ) ) ;
entry -> gc_handle = gc_handle ;
entry -> flags = flags ;
CFDictionarySetValue ( gchandle_hash , self , entry ) ;
2016-04-21 15:19:32 +03:00
}
pthread_mutex _unlock ( & gchandle_hash _lock ) ;
2021-04-23 19:42:11 +03:00
return true ;
2016-04-21 15:19:32 +03:00
}
2021-02-11 10:18:38 +03:00
GCHandle
2016-04-21 15:19:32 +03:00
xamarin_get _gchandle _trampoline ( id self , SEL sel )
{
2016-02-15 21:02:14 +03:00
// COOP : Called by ObjC ( when the getGCHandle selector is called on an object ) .
// COOP : Safe mode upon entry , and doesn ' t access managed memory , so no need to switch .
MONO_ASSERT _GC _SAFE ;
2016-04-21 15:19:32 +03:00
/ * This is for types registered using the dynamic registrar * /
2021-02-11 10:18:38 +03:00
GCHandle gc_handle = INVALID_GCHANDLE ;
2016-04-21 15:19:32 +03:00
pthread_mutex _lock ( & gchandle_hash _lock ) ;
2021-02-11 10:18:38 +03:00
if ( gchandle_hash ! = NULL ) {
struct gchandle_dictionary _entry * entry ;
entry = ( struct gchandle_dictionary _entry * ) CFDictionaryGetValue ( gchandle_hash , self ) ;
if ( entry ! = NULL )
gc_handle = entry -> gc_handle ;
}
2016-04-21 15:19:32 +03:00
pthread_mutex _unlock ( & gchandle_hash _lock ) ;
return gc_handle ;
}
2017-07-03 20:18:02 +03:00
2021-02-11 10:18:38 +03:00
enum XamarinGCHandleFlags
xamarin_get _flags _trampoline ( id self , SEL sel )
{
// COOP : Called by ObjC ( when the getFlags selector is called on an object ) .
// COOP : Safe mode upon entry , and doesn ' t access managed memory , so no need to switch .
MONO_ASSERT _GC _SAFE ;
/ * This is for types registered using the dynamic registrar * /
enum XamarinGCHandleFlags flags = XamarinGCHandleFlags_None ;
pthread_mutex _lock ( & gchandle_hash _lock ) ;
if ( gchandle_hash ! = NULL ) {
struct gchandle_dictionary _entry * entry ;
entry = ( struct gchandle_dictionary _entry * ) CFDictionaryGetValue ( gchandle_hash , self ) ;
if ( entry ! = NULL )
flags = entry -> flags ;
}
pthread_mutex _unlock ( & gchandle_hash _lock ) ;
return flags ;
}
void
xamarin_set _flags _trampoline ( id self , SEL sel , enum XamarinGCHandleFlags flags )
{
// COOP : Called by ObjC ( when the setFlags : selector is called on an object ) .
// COOP : Safe mode upon entry , and doesn ' t access managed memory , so no need to switch .
MONO_ASSERT _GC _SAFE ;
/ * This is for types registered using the dynamic registrar * /
pthread_mutex _lock ( & gchandle_hash _lock ) ;
if ( gchandle_hash ! = NULL ) {
struct gchandle_dictionary _entry * entry ;
entry = ( struct gchandle_dictionary _entry * ) CFDictionaryGetValue ( gchandle_hash , self ) ;
if ( entry ! = NULL )
entry -> flags = flags ;
}
pthread_mutex _unlock ( & gchandle_hash _lock ) ;
}
2017-07-03 20:18:02 +03:00
id
2021-02-11 10:18:38 +03:00
xamarin_generate _conversion _to _native ( MonoObject * value , MonoType * inputType , MonoType * outputType , MonoMethod * method , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
// COOP : Reads managed memory , needs to be in UNSAFE mode
MONO_ASSERT _GC _UNSAFE ;
// This method is a mirror of StaticRegistrar . GenerateConversionToNative
// These methods must be kept in sync .
id convertedValue = NULL ;
MonoClass * managedType = mono_class _from _mono _type ( inputType ) ;
MonoClass * nativeType = mono_class _from _mono _type ( outputType ) ;
MonoClass * underlyingManagedType = managedType ;
MonoClass * underlyingNativeType = nativeType ;
bool isManagedArray = xamarin_is _class _array ( managedType ) ;
bool isNativeArray = xamarin_is _class _array ( nativeType ) ;
2017-07-04 19:33:31 +03:00
MonoClass * nullableManagedType = NULL ;
bool isManagedNullable = xamarin_is _class _nullable ( managedType , & nullableManagedType , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-04 19:33:31 +03:00
goto exception_handling ;
2017-07-03 20:18:02 +03:00
if ( isManagedArray ! = isNativeArray ) {
* exception_gchandle = xamarin_create _bindas _exception ( inputType , outputType , method ) ;
goto exception_handling ;
}
if ( isManagedArray ) {
if ( isManagedNullable ) {
* exception_gchandle = xamarin_create _bindas _exception ( inputType , outputType , method ) ;
goto exception_handling ;
}
underlyingNativeType = mono_class _get _element _class ( nativeType ) ;
underlyingManagedType = mono_class _get _element _class ( managedType ) ;
} else if ( isManagedNullable ) {
2017-07-04 19:33:31 +03:00
underlyingManagedType = nullableManagedType ;
2017-07-03 20:18:02 +03:00
}
if ( value ) {
xamarin_managed _to _id _func func ;
if ( xamarin_is _class _nsnumber ( underlyingNativeType ) ) {
func = xamarin_get _managed _to _nsnumber _func ( underlyingManagedType , method , exception_gchandle ) ;
} else if ( xamarin_is _class _nsvalue ( underlyingNativeType ) ) {
func = xamarin_get _managed _to _nsvalue _func ( underlyingManagedType , method , exception_gchandle ) ;
} else if ( xamarin_is _class _nsstring ( underlyingNativeType ) ) {
func = xamarin_get _smart _enum _to _nsstring _func ( underlyingManagedType , method , exception_gchandle ) ;
} else {
* exception_gchandle = xamarin_create _bindas _exception ( inputType , outputType , method ) ;
goto exception_handling ;
}
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
if ( isManagedArray ) {
2018-02-05 09:54:13 +03:00
convertedValue = xamarin_convert _managed _to _nsarray _with _func ( ( MonoArray * ) value , func , context , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
} else {
2018-02-05 09:54:13 +03:00
convertedValue = func ( value , context , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
}
}
exception_handling :
return convertedValue ;
}
void *
2021-02-11 10:18:38 +03:00
xamarin_generate _conversion _to _managed ( id value , MonoType * inputType , MonoType * outputType , MonoMethod * method , GCHandle * exception_gchandle , void * context , / * SList * / void * * free_list )
2017-07-03 20:18:02 +03:00
{
// COOP : Reads managed memory , needs to be in UNSAFE mode
MONO_ASSERT _GC _UNSAFE ;
// This method is a mirror of StaticRegistrar . GenerateConversionToManaged
// These methods must be kept in sync .
void * convertedValue = NULL ;
MonoClass * managedType = mono_class _from _mono _type ( outputType ) ;
MonoClass * nativeType = mono_class _from _mono _type ( inputType ) ;
MonoClass * underlyingManagedType = managedType ;
MonoClass * underlyingNativeType = nativeType ;
bool isManagedArray = xamarin_is _class _array ( managedType ) ;
bool isNativeArray = xamarin_is _class _array ( nativeType ) ;
2017-07-04 19:33:31 +03:00
MonoClass * nullableManagedType = NULL ;
bool isManagedNullable = xamarin_is _class _nullable ( managedType , & nullableManagedType , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-04 19:33:31 +03:00
goto exception_handling ;
2017-07-03 20:18:02 +03:00
if ( isManagedArray ! = isNativeArray ) {
* exception_gchandle = xamarin_create _bindas _exception ( inputType , outputType , method ) ;
goto exception_handling ;
}
if ( isManagedArray ) {
if ( isManagedNullable ) {
* exception_gchandle = xamarin_create _bindas _exception ( inputType , outputType , method ) ;
goto exception_handling ;
}
underlyingNativeType = mono_class _get _element _class ( nativeType ) ;
underlyingManagedType = mono_class _get _element _class ( managedType ) ;
} else if ( isManagedNullable ) {
2017-07-04 19:33:31 +03:00
underlyingManagedType = nullableManagedType ;
2017-07-03 20:18:02 +03:00
}
if ( value ) {
xamarin_id _to _managed _func func ;
if ( xamarin_is _class _nsnumber ( underlyingNativeType ) ) {
func = xamarin_get _nsnumber _to _managed _func ( underlyingManagedType , method , exception_gchandle ) ;
} else if ( xamarin_is _class _nsvalue ( underlyingNativeType ) ) {
func = xamarin_get _nsvalue _to _managed _func ( underlyingManagedType , method , exception_gchandle ) ;
} else if ( xamarin_is _class _nsstring ( underlyingNativeType ) ) {
func = xamarin_get _nsstring _to _smart _enum _func ( underlyingManagedType , method , exception_gchandle ) ;
} else {
* exception_gchandle = xamarin_create _bindas _exception ( inputType , outputType , method ) ;
goto exception_handling ;
}
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
if ( isManagedArray ) {
2018-02-05 09:54:13 +03:00
convertedValue = xamarin_convert _nsarray _to _managed _with _func ( value , underlyingManagedType , func , context , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
} else {
2018-02-05 09:54:13 +03:00
convertedValue = func ( value , NULL , underlyingManagedType , context , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
* ( SList * * ) free_list = s_list _prepend (*(SList **) free_list , convertedValue ) ;
if ( isManagedNullable )
convertedValue = mono_value _box ( mono_domain _get ( ) , underlyingManagedType , convertedValue ) ;
}
}
exception_handling :
return convertedValue ;
}
2017-09-22 12:58:37 +03:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunguarded-availability-new"
2017-07-03 20:18:02 +03:00
// Returns a pointer to the value type , which must be freed using xamarin_free .
// If called multiple times in succession , the returned pointer can be passed as the second ptr argument , and it need only be freed once done iterating .
2021-02-11 10:18:38 +03:00
void * xamarin_nsnumber _to _bool ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { BOOL * valueptr = ( BOOL * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( BOOL ) ) ) ; * valueptr = [ number boolValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _sbyte ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { int8_t * valueptr = ( int8_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( int8_t ) ) ) ; * valueptr = [ number charValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _byte ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { uint8_t * valueptr = ( uint8_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( uint8_t ) ) ) ; * valueptr = [ number unsignedCharValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _short ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { int16_t * valueptr = ( int16_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( int16_t ) ) ) ; * valueptr = [ number shortValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _ushort ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { uint16_t * valueptr = ( uint16_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( uint16_t ) ) ) ; * valueptr = [ number unsignedShortValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _int ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { int32_t * valueptr = ( int32_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( int32_t ) ) ) ; * valueptr = [ number intValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _uint ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { uint32_t * valueptr = ( uint32_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( uint32_t ) ) ) ; * valueptr = [ number unsignedIntValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _long ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { int64_t * valueptr = ( int64_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( int64_t ) ) ) ; * valueptr = [ number longLongValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _ulong ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { uint64_t * valueptr = ( uint64_t * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( uint64_t ) ) ) ; * valueptr = [ number unsignedLongLongValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _nint ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { NSInteger * valueptr = ( NSInteger * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( NSInteger ) ) ) ; * valueptr = [ number integerValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _nuint ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { NSUInteger * valueptr = ( NSUInteger * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( NSUInteger ) ) ) ; * valueptr = [ number unsignedIntegerValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _float ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { float * valueptr = ( float * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( float ) ) ) ; * valueptr = [ number floatValue ] ; return valueptr ; }
void * xamarin_nsnumber _to _double ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { double * valueptr = ( double * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( double ) ) ) ; * valueptr = [ number doubleValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# if __POINTER _WIDTH __ = = 32
2021-02-11 10:18:38 +03:00
void * xamarin_nsnumber _to _nfloat ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { float * valueptr = ( float * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( float ) ) ) ; * valueptr = [ number floatValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# elif __POINTER _WIDTH __ = = 64
2021-02-11 10:18:38 +03:00
void * xamarin_nsnumber _to _nfloat ( NSNumber * number , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { double * valueptr = ( double * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( double ) ) ) ; * valueptr = [ number doubleValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# else
# error Invalid pointer size .
# endif
// Returns a pointer to the value type , which must be freed using xamarin_free .
// If called multiple times in succession , the returned pointer can be passed as the second ptr argument , and it need only be freed once done iterating .
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _nsrange ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { NSRange * valueptr = ( NSRange * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( NSRange ) ) ) ; * valueptr = [ value rangeValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# if HAVE_UIKIT // Yep , these CoreGraphics - looking category method is defined in UIKit .
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _cgaffinetransform ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CGAffineTransform * valueptr = ( CGAffineTransform * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CGAffineTransform ) ) ) ; * valueptr = [ value CGAffineTransformValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _cgpoint ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CGPoint * valueptr = ( CGPoint * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CGPoint ) ) ) ; * valueptr = [ value CGPointValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _cgrect ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CGRect * valueptr = ( CGRect * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CGRect ) ) ) ; * valueptr = [ value CGRectValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _cgsize ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CGSize * valueptr = ( CGSize * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CGSize ) ) ) ; * valueptr = [ value CGSizeValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _cgvector ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CGVector * valueptr = ( CGVector * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CGVector ) ) ) ; * valueptr = [ value CGVectorValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _nsdirectionaledgeinsets ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { NSDirectionalEdgeInsets * valueptr = ( NSDirectionalEdgeInsets * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( NSDirectionalEdgeInsets ) ) ) ; * valueptr = [ value directionalEdgeInsetsValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREANIMATION
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _catransform3d ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CATransform3D * valueptr = ( CATransform3D * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CATransform3D ) ) ) ; * valueptr = [ value CATransform3DValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_MAPKIT // Yep , this is defined in MapKit .
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _cllocationcoordinate2d ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CLLocationCoordinate2D * valueptr = ( CLLocationCoordinate2D * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CLLocationCoordinate2D ) ) ) ; * valueptr = [ value MKCoordinateValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREMEDIA
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _cmtime ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CMTime * valueptr = ( CMTime * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CMTime ) ) ) ; * valueptr = [ value CMTimeValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _cmtimemapping ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CMTimeMapping * valueptr = ( CMTimeMapping * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CMTimeMapping ) ) ) ; * valueptr = [ value CMTimeMappingValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _cmtimerange ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { CMTimeRange * valueptr = ( CMTimeRange * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( CMTimeRange ) ) ) ; * valueptr = [ value CMTimeRangeValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_MAPKIT
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _mkcoordinatespan ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { MKCoordinateSpan * valueptr = ( MKCoordinateSpan * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( MKCoordinateSpan ) ) ) ; * valueptr = [ value MKCoordinateSpanValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# endif
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _scnmatrix4 ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { SCNMatrix4 * valueptr = ( SCNMatrix4 * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( SCNMatrix4 ) ) ) ; * valueptr = [ value SCNMatrix4Value ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
void *
2021-02-11 10:18:38 +03:00
xamarin_nsvalue _to _scnvector3 ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
# if TARGET_OS _IOS && defined ( __arm __ )
// In earlier versions of iOS [ NSValue SCNVector3Value ] would return 4
// floats . This does not cause problems on 64 - bit architectures , because
// the 4 floats end up in floating point registers that doesn ' t need to be
// preserved . On 32 - bit architectures it becomes a real problem though ,
// since objc_msgSend _stret will be called , and the return value will be
// written to the stack . Writing 4 floats to the stack , when clang
// allocates 3 bytes , is a bad idea . There ' s no radar since this has
// already been fixed in iOS , it only affects older versions .
// So we have to avoid the SCNVector3Value selector on 32 - bit
// architectures , since we can ' t influence how clang generates the call .
// Instead use [ NSValue getValue : ] . Interestingly enough this function has
// the same bug : it will write 4 floats on 32 - bit architectures ( and
// amazingly 4 * doubles * on 64 - bit architectures - this has been filed as
// radar 33104111 ) , but since we control the input buffer , we can just
// allocate the necessary bytes . And for good measure allocate 32 bytes ,
// just to be sure .
// Just to complicate matters , everything works fine on watchOS because
// armv7k does not use objc_msgSend _stret for this signature , this only
// happens on iOS .
SCNVector3 * valueptr = ( SCNVector3 * ) xamarin_calloc ( 32 ) ;
[ value getValue : valueptr ] ;
if ( ptr ) {
memcpy ( ptr , valueptr , sizeof ( SCNVector3 ) ) ;
xamarin_free ( valueptr ) ;
valueptr = ( SCNVector3 * ) ptr ;
}
# else
SCNVector3 * valueptr = ( SCNVector3 * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( SCNVector3 ) ) ) ;
* valueptr = [ value SCNVector3Value ] ;
# endif
return valueptr ;
}
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _scnvector4 ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { SCNVector4 * valueptr = ( SCNVector4 * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( SCNVector4 ) ) ) ; * valueptr = [ value SCNVector4Value ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# if HAVE_UIKIT
2021-02-11 10:18:38 +03:00
void * xamarin_nsvalue _to _uiedgeinsets ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { UIEdgeInsets * valueptr = ( UIEdgeInsets * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( UIEdgeInsets ) ) ) ; * valueptr = [ value UIEdgeInsetsValue ] ; return valueptr ; }
void * xamarin_nsvalue _to _uioffset ( NSValue * value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle ) { UIOffset * valueptr = ( UIOffset * ) ( ptr ? ptr : xamarin_calloc ( sizeof ( UIOffset ) ) ) ; * valueptr = [ value UIOffsetValue ] ; return valueptr ; }
2017-07-03 20:18:02 +03:00
# endif
2021-02-11 10:18:38 +03:00
id xamarin_bool _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithBool : * ( BOOL * ) mono_object _unbox ( value ) ] ; }
id xamarin_sbyte _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithChar : * ( int8_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_byte _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithUnsignedChar : * ( uint8_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_short _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithShort : * ( int16_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_ushort _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithUnsignedShort : * ( uint16_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_int _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithInt : * ( int32_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_uint _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithUnsignedInt : * ( uint32_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_long _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithLongLong : * ( int64_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_ulong _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithUnsignedLongLong : * ( uint64_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_nint _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithInteger : * ( NSInteger * ) mono_object _unbox ( value ) ] ; }
id xamarin_nuint _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithUnsignedInteger : * ( NSUInteger * ) mono_object _unbox ( value ) ] ; }
id xamarin_float _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithFloat : * ( float * ) mono_object _unbox ( value ) ] ; }
id xamarin_double _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithDouble : * ( double * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# if __POINTER _WIDTH __ = = 32
2021-02-11 10:18:38 +03:00
id xamarin_nfloat _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithFloat : * ( float * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# elif __POINTER _WIDTH __ = = 64
2021-02-11 10:18:38 +03:00
id xamarin_nfloat _to _nsnumber ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSNumber numberWithDouble : * ( double * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# else
# error Invalid pointer size .
# endif
2021-02-11 10:18:38 +03:00
id xamarin_nsrange _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithRange : * ( NSRange * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# if HAVE_UIKIT // yep , these CoreGraphics - looking category methods are defined in UIKit
2021-02-11 10:18:38 +03:00
id xamarin_cgaffinetransform _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCGAffineTransform : * ( CGAffineTransform * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgpoint _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCGPoint : * ( CGPoint * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgrect _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCGRect : * ( CGRect * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgsize _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCGSize : * ( CGSize * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgvector _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCGVector : * ( CGVector * ) mono_object _unbox ( value ) ] ; }
id xamarin_nsdirectionaledgeinsets _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithDirectionalEdgeInsets : * ( NSDirectionalEdgeInsets * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREANIMATION
2021-02-11 10:18:38 +03:00
id xamarin_catransform3d _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCATransform3D : * ( CATransform3D * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_MAPKIT // Yep , this is defined in MapKit .
2021-02-11 10:18:38 +03:00
id xamarin_cllocationcoordinate2d _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithMKCoordinate : * ( CLLocationCoordinate2D * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREMEDIA
2021-02-11 10:18:38 +03:00
id xamarin_cmtime _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCMTime : * ( CMTime * ) mono_object _unbox ( value ) ] ; }
id xamarin_cmtimemapping _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCMTimeMapping : * ( CMTimeMapping * ) mono_object _unbox ( value ) ] ; }
id xamarin_cmtimerange _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithCMTimeRange : * ( CMTimeRange * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_MAPKIT
2021-02-11 10:18:38 +03:00
id xamarin_mkcoordinatespan _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithMKCoordinateSpan : * ( MKCoordinateSpan * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
2021-02-11 10:18:38 +03:00
id xamarin_scnmatrix4 _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithSCNMatrix4 : * ( SCNMatrix4 * ) mono_object _unbox ( value ) ] ; }
id xamarin_scnvector3 _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithSCNVector3 : * ( SCNVector3 * ) mono_object _unbox ( value ) ] ; }
id xamarin_scnvector4 _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithSCNVector4 : * ( SCNVector4 * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# if HAVE_UIKIT
2021-02-11 10:18:38 +03:00
id xamarin_uiedgeinsets _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithUIEdgeInsets : * ( UIEdgeInsets * ) mono_object _unbox ( value ) ] ; }
id xamarin_uioffset _to _nsvalue ( MonoObject * value , void * context , GCHandle * exception_gchandle ) { return [ NSValue valueWithUIOffset : * ( UIOffset * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
2017-09-22 12:58:37 +03:00
# pragma clang diagnostic pop
2019-04-22 18:50:38 +03:00
struct conversion_data {
MonoDomain * domain ;
MonoType * element_type ;
MonoClass * element_class ;
MonoReflectionType * element_reflection _type ;
2019-04-23 08:59:32 +03:00
uint32_t iface_token _ref ;
uint32_t implementation_token _ref ;
2019-04-22 18:50:38 +03:00
} ;
2019-04-22 18:45:10 +03:00
id
2021-02-11 10:18:38 +03:00
xamarin_convert _string _to _nsstring ( MonoObject * obj , void * context , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
return xamarin_string _to _nsstring ( ( MonoString * ) obj , false ) ;
}
2019-04-22 18:50:38 +03:00
void *
2021-02-11 10:18:38 +03:00
xamarin_convert _nsstring _to _string ( id value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
return xamarin_nsstring _to _string ( NULL , ( NSString * ) value ) ;
}
2019-04-22 18:45:10 +03:00
id
2021-02-11 10:18:38 +03:00
xamarin_object _to _nsobject ( MonoObject * object , void * context , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
return xamarin_get _nsobject _handle ( object ) ;
}
id
2021-02-11 10:18:38 +03:00
xamarin_inativeobject _to _nsobject ( MonoObject * object , void * context , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
return xamarin_get _handle _for _inativeobject ( object , exception_gchandle ) ;
}
2019-04-22 18:50:38 +03:00
void *
2021-02-11 10:18:38 +03:00
xamarin_nsobject _to _object ( id object , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
struct conversion_data * data = ( struct conversion_data * ) context ;
return xamarin_get _nsobject _with _type _for _ptr ( object , false , data -> element_type , exception_gchandle ) ;
}
void *
2021-02-11 10:18:38 +03:00
xamarin_nsobject _to _inativeobject ( id object , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
struct conversion_data * data = ( struct conversion_data * ) context ;
return xamarin_get _inative _object _dynamic ( object , false , data -> element_reflection _type , exception_gchandle ) ;
}
2019-04-23 08:59:32 +03:00
void *
2021-02-11 10:18:38 +03:00
xamarin_nsobject _to _inativeobject _static ( id object , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle )
2019-04-23 08:59:32 +03:00
{
struct conversion_data * data = ( struct conversion_data * ) context ;
return xamarin_get _inative _object _static ( object , false , data -> iface_token _ref , data -> implementation_token _ref , exception_gchandle ) ;
}
2019-04-22 18:45:10 +03:00
NSArray *
2021-02-11 10:18:38 +03:00
xamarin_managed _string _array _to _nsarray ( MonoArray * array , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
return xamarin_convert _managed _to _nsarray _with _func ( array , xamarin_convert _string _to _nsstring , 0 , exception_gchandle ) ;
}
NSArray *
2021-02-11 10:18:38 +03:00
xamarin_managed _nsobject _array _to _nsarray ( MonoArray * array , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
return xamarin_convert _managed _to _nsarray _with _func ( array , xamarin_object _to _nsobject , 0 , exception_gchandle ) ;
}
NSArray *
2021-02-11 10:18:38 +03:00
xamarin_managed _inativeobject _array _to _nsarray ( MonoArray * array , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
return xamarin_convert _managed _to _nsarray _with _func ( array , xamarin_inativeobject _to _nsobject , 0 , exception_gchandle ) ;
}
NSArray *
2021-02-11 10:18:38 +03:00
xamarin_managed _array _to _nsarray ( MonoArray * array , MonoType * managed_type , MonoClass * managed_class , GCHandle * exception_gchandle )
2019-04-22 18:45:10 +03:00
{
if ( array = = NULL )
return NULL ;
if ( managed_class = = NULL )
managed_class = mono_class _from _mono _type ( managed_type ) ;
MonoClass * e_klass = mono_class _get _element _class ( managed_class ) ;
if ( e_klass = = mono_get _string _class ( ) ) {
return xamarin_managed _string _array _to _nsarray ( array , exception_gchandle ) ;
} else if ( xamarin_is _class _nsobject ( e_klass ) ) {
return xamarin_managed _nsobject _array _to _nsarray ( array , exception_gchandle ) ;
} else if ( xamarin_is _class _inativeobject ( e_klass ) ) {
return xamarin_managed _inativeobject _array _to _nsarray ( array , exception_gchandle ) ;
}
// Don ' t know how to convert : show an exception .
char * element_name = xamarin_type _get _full _name ( mono_class _get _type ( e_klass ) , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2019-04-22 18:45:10 +03:00
return NULL ;
char * msg = xamarin_strdup _printf ( "Unable to convert from a managed array of %s to an NSArray." , element_name ) ;
* exception_gchandle = xamarin_create _product _exception _with _inner _exception ( 8032 , * exception_gchandle , msg ) ;
xamarin_free ( msg ) ;
xamarin_free ( element_name ) ;
return NULL ;
}
2019-04-22 18:50:38 +03:00
MonoArray *
2021-02-11 10:18:38 +03:00
xamarin_nsarray _to _managed _string _array ( NSArray * array , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
return xamarin_convert _nsarray _to _managed _with _func ( array , mono_get _string _class ( ) , xamarin_convert _nsstring _to _string , 0 , exception_gchandle ) ;
}
MonoArray *
2021-02-11 10:18:38 +03:00
xamarin_nsarray _to _managed _nsobject _array ( NSArray * array , MonoType * array_type , MonoClass * element_class , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
struct conversion_data data = { 0 } ;
data . domain = mono_domain _get ( ) ;
data . element_class = element_class = = NULL ? mono_class _get _element _class ( mono_class _from _mono _type ( array_type ) ) : element_class ;
data . element_type = mono_class _get _type ( data . element_class ) ;
data . element_reflection _type = mono_type _get _object ( data . domain , data . element_type ) ;
return xamarin_convert _nsarray _to _managed _with _func ( array , data . element_class , xamarin_nsobject _to _object , & data , exception_gchandle ) ;
}
MonoArray *
2021-02-11 10:18:38 +03:00
xamarin_nsarray _to _managed _inativeobject _array ( NSArray * array , MonoType * array_type , MonoClass * element_class , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
struct conversion_data data = { 0 } ;
data . domain = mono_domain _get ( ) ;
data . element_class = element_class = = NULL ? mono_class _get _element _class ( mono_class _from _mono _type ( array_type ) ) : element_class ;
data . element_type = mono_class _get _type ( data . element_class ) ;
data . element_reflection _type = mono_type _get _object ( data . domain , data . element_type ) ;
return xamarin_convert _nsarray _to _managed _with _func ( array , data . element_class , xamarin_nsobject _to _inativeobject , & data , exception_gchandle ) ;
}
2019-04-23 08:59:32 +03:00
MonoArray *
2021-02-11 10:18:38 +03:00
xamarin_nsarray _to _managed _inativeobject _array _static ( NSArray * array , MonoType * array_type , MonoClass * element_class , uint32_t iface_token _ref , uint32_t implementation_token _ref , GCHandle * exception_gchandle )
2019-04-23 08:59:32 +03:00
{
struct conversion_data data = { 0 } ;
data . element_class = element_class = = NULL ? mono_class _get _element _class ( mono_class _from _mono _type ( array_type ) ) : element_class ;
data . element_type = mono_class _get _type ( data . element_class ) ;
data . iface_token _ref = iface_token _ref ;
data . implementation_token _ref = implementation_token _ref ;
return xamarin_convert _nsarray _to _managed _with _func ( array , data . element_class , xamarin_nsobject _to _inativeobject _static , & data , exception_gchandle ) ;
}
2019-04-22 18:50:38 +03:00
MonoArray *
2021-02-11 10:18:38 +03:00
xamarin_nsarray _to _managed _array ( NSArray * array , MonoType * managed_type , MonoClass * managed_class , GCHandle * exception_gchandle )
2019-04-22 18:50:38 +03:00
{
if ( array = = NULL )
return NULL ;
if ( managed_class = = NULL )
managed_class = mono_class _from _mono _type ( managed_type ) ;
MonoClass * e_klass = mono_class _get _element _class ( managed_class ) ;
if ( e_klass = = mono_get _string _class ( ) ) {
return xamarin_nsarray _to _managed _string _array ( array , exception_gchandle ) ;
} else if ( xamarin_is _class _nsobject ( e_klass ) ) {
return xamarin_nsarray _to _managed _nsobject _array ( array , managed_type , e_klass , exception_gchandle ) ;
} else if ( xamarin_is _class _inativeobject ( e_klass ) ) {
return xamarin_nsarray _to _managed _inativeobject _array ( array , managed_type , e_klass , exception_gchandle ) ;
}
// Don ' t know how to convert : show an exception .
char * element_name = xamarin_type _get _full _name ( mono_class _get _type ( e_klass ) , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2019-04-22 18:50:38 +03:00
return NULL ;
char * msg = xamarin_strdup _printf ( "Unable to convert from an NSArray to a managed array of %s." , element_name ) ;
* exception_gchandle = xamarin_create _product _exception _with _inner _exception ( 8031 , * exception_gchandle , msg ) ;
xamarin_free ( msg ) ;
xamarin_free ( element_name ) ;
return NULL ;
}
2017-07-03 20:18:02 +03:00
static void *
2021-02-11 10:18:38 +03:00
xamarin_get _nsnumber _converter ( MonoClass * managedType , MonoMethod * method , bool to_managed , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
2017-07-05 11:54:45 +03:00
int type ;
2017-07-03 20:18:02 +03:00
void * func = NULL ;
char * fullname = xamarin_class _get _full _name ( managedType , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
2017-07-05 11:54:45 +03:00
type = mono_type _get _type ( mono_class _get _type ( managedType ) ) ;
switch ( type ) {
case MONO_TYPE _I1 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _sbyte : ( void * ) xamarin_sbyte _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _U1 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _byte : ( void * ) xamarin_byte _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _I2 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _short : ( void * ) xamarin_short _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _U2 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _ushort : ( void * ) xamarin_ushort _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _I4 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _int : ( void * ) xamarin_int _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _U4 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _uint : ( void * ) xamarin_uint _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _I8 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _long : ( void * ) xamarin_long _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _U8 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _ulong : ( void * ) xamarin_ulong _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _R4 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _float : ( void * ) xamarin_float _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _R8 :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _double : ( void * ) xamarin_double _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
case MONO_TYPE _BOOLEAN :
2017-07-03 20:18:02 +03:00
func = to_managed ? ( void * ) xamarin_nsnumber _to _bool : ( void * ) xamarin_bool _to _nsnumber ;
2017-07-05 11:54:45 +03:00
break ;
default :
if ( ! strcmp ( fullname , "System.nint" ) ) {
func = to_managed ? ( void * ) xamarin_nsnumber _to _nint : ( void * ) xamarin_nint _to _nsnumber ;
} else if ( ! strcmp ( fullname , "System.nuint" ) ) {
func = to_managed ? ( void * ) xamarin_nsnumber _to _nuint : ( void * ) xamarin_nuint _to _nsnumber ;
} else if ( ! strcmp ( fullname , "System.nfloat" ) ) {
func = to_managed ? ( void * ) xamarin_nsnumber _to _nfloat : ( void * ) xamarin_nfloat _to _nsnumber ;
2017-07-06 18:25:01 +03:00
} else if ( mono_class _is _enum ( managedType ) ) {
func = xamarin_get _nsnumber _converter ( mono_class _from _mono _type ( mono_class _enum _basetype ( managedType ) ) , method , to_managed , exception_gchandle ) ;
2017-07-05 11:54:45 +03:00
} else {
* exception_gchandle = xamarin_create _bindas _exception ( mono_class _get _type ( managedType ) , mono_class _get _type ( xamarin_get _nsnumber _class ( ) ) , method ) ;
goto exception_handling ;
}
2017-07-03 20:18:02 +03:00
}
exception_handling :
xamarin_free ( fullname ) ;
return func ;
}
static void *
2021-02-11 10:18:38 +03:00
xamarin_get _nsvalue _converter ( MonoClass * managedType , MonoMethod * method , bool to_managed , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
void * func = NULL ;
char * fullname = xamarin_class _get _full _name ( managedType , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
if ( ! strcmp ( fullname , "Foundation.NSRange" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _nsrange : ( void * ) xamarin_nsrange _to _nsvalue ;
# if HAVE_UIKIT // yep , these CoreGraphics - looking category methods are defined in UIKit
} else if ( ! strcmp ( fullname , "CoreGraphics.CGAffineTransform" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cgaffinetransform : ( void * ) xamarin_cgaffinetransform _to _nsvalue ;
} else if ( ! strcmp ( fullname , "CoreGraphics.CGPoint" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cgpoint : ( void * ) xamarin_cgpoint _to _nsvalue ;
} else if ( ! strcmp ( fullname , "CoreGraphics.CGRect" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cgrect : ( void * ) xamarin_cgrect _to _nsvalue ;
} else if ( ! strcmp ( fullname , "CoreGraphics.CGSize" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cgsize : ( void * ) xamarin_cgsize _to _nsvalue ;
} else if ( ! strcmp ( fullname , "CoreGraphics.CGVector" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cgvector : ( void * ) xamarin_cgvector _to _nsvalue ;
2017-09-22 13:00:08 +03:00
} else if ( ! strcmp ( fullname , "UIKit.NSDirectionalEdgeInsets" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _nsdirectionaledgeinsets : ( void * ) xamarin_nsdirectionaledgeinsets _to _nsvalue ;
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREANIMATION
} else if ( ! strcmp ( fullname , "CoreAnimation.CATransform3D" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _catransform3d : ( void * ) xamarin_catransform3d _to _nsvalue ;
# endif
# if HAVE_MAPKIT // Yep , this is defined in MapKit .
} else if ( ! strcmp ( fullname , "CoreLocation.CLLocationCoordinate2D" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cllocationcoordinate2d : ( void * ) xamarin_cllocationcoordinate2d _to _nsvalue ;
# endif
# if HAVE_COREMEDIA
} else if ( ! strcmp ( fullname , "CoreMedia.CMTime" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cmtime : ( void * ) xamarin_cmtime _to _nsvalue ;
} else if ( ! strcmp ( fullname , "CoreMedia.CMTimeMapping" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cmtimemapping : ( void * ) xamarin_cmtimemapping _to _nsvalue ;
} else if ( ! strcmp ( fullname , "CoreMedia.CMTimeRange" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _cmtimerange : ( void * ) xamarin_cmtimerange _to _nsvalue ;
# endif
# if HAVE_MAPKIT
} else if ( ! strcmp ( fullname , "MapKit.MKCoordinateSpan" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _mkcoordinatespan : ( void * ) xamarin_mkcoordinatespan _to _nsvalue ;
# endif
} else if ( ! strcmp ( fullname , "SceneKit.SCNMatrix4" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _scnmatrix4 : ( void * ) xamarin_scnmatrix4 _to _nsvalue ;
} else if ( ! strcmp ( fullname , "SceneKit.SCNVector3" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _scnvector3 : ( void * ) xamarin_scnvector3 _to _nsvalue ;
} else if ( ! strcmp ( fullname , "SceneKit.SCNVector4" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _scnvector4 : ( void * ) xamarin_scnvector4 _to _nsvalue ;
# if HAVE_UIKIT
} else if ( ! strcmp ( fullname , "UIKit.UIEdgeInsets" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _uiedgeinsets : ( void * ) xamarin_uiedgeinsets _to _nsvalue ;
} else if ( ! strcmp ( fullname , "UIKit.UIOffset" ) ) {
func = to_managed ? ( void * ) xamarin_nsvalue _to _uioffset : ( void * ) xamarin_uioffset _to _nsvalue ;
# endif
} else {
* exception_gchandle = xamarin_create _bindas _exception ( mono_class _get _type ( managedType ) , mono_class _get _type ( xamarin_get _nsvalue _class ( ) ) , method ) ;
goto exception_handling ;
}
exception_handling :
xamarin_free ( fullname ) ;
return func ;
}
xamarin_id _to _managed _func
2021-02-11 10:18:38 +03:00
xamarin_get _nsnumber _to _managed _func ( MonoClass * managedType , MonoMethod * method , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
return ( xamarin_id _to _managed _func ) xamarin_get _nsnumber _converter ( managedType , method , true , exception_gchandle ) ;
}
xamarin_managed _to _id _func
2021-02-11 10:18:38 +03:00
xamarin_get _managed _to _nsnumber _func ( MonoClass * managedType , MonoMethod * method , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
return ( xamarin_managed _to _id _func ) xamarin_get _nsnumber _converter ( managedType , method , false , exception_gchandle ) ;
}
xamarin_id _to _managed _func
2021-02-11 10:18:38 +03:00
xamarin_get _nsvalue _to _managed _func ( MonoClass * managedType , MonoMethod * method , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
return ( xamarin_id _to _managed _func ) xamarin_get _nsvalue _converter ( managedType , method , true , exception_gchandle ) ;
}
xamarin_managed _to _id _func
2021-02-11 10:18:38 +03:00
xamarin_get _managed _to _nsvalue _func ( MonoClass * managedType , MonoMethod * method , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
return ( xamarin_managed _to _id _func ) xamarin_get _nsvalue _converter ( managedType , method , false , exception_gchandle ) ;
}
void *
2021-02-11 10:18:38 +03:00
xamarin_smart _enum _to _nsstring ( MonoObject * value , void * context / * token ref * / , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
2019-11-12 23:10:16 +03:00
guint32 context_ref = GPOINTER_TO _UINT ( context ) ;
2019-04-05 19:58:45 +03:00
if ( context_ref = = INVALID_TOKEN _REF ) {
2018-02-05 09:54:13 +03:00
// This requires the dynamic registrar to invoke the correct conversion function
2020-05-04 12:08:44 +03:00
NSString * rv = xamarin_convert _smart _enum _to _nsstring ( value , exception_gchandle ) ;
2018-02-05 09:54:13 +03:00
return rv ;
} 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 .
MonoMethod * managed_method ;
MonoObject * exception = NULL ;
MonoObject * retval ;
void * arg_ptrs [ 1 ] ;
2019-04-05 19:58:45 +03:00
managed_method = xamarin_get _managed _method _for _token ( context_ref / * token ref * / , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE ) return NULL ;
2018-02-05 09:54:13 +03:00
arg_ptrs [ 0 ] = mono_object _unbox ( value ) ;
retval = mono_runtime _invoke ( managed_method , NULL , arg_ptrs , & exception ) ;
2021-04-30 08:49:25 +03:00
xamarin_mono _object _release ( & managed_method ) ;
2018-02-05 09:54:13 +03:00
if ( exception ) {
2021-02-11 10:18:38 +03:00
* exception_gchandle = xamarin_gchandle _new ( exception , FALSE ) ;
2018-02-05 09:54:13 +03:00
return NULL ;
}
if ( retval = = NULL )
return NULL ;
2021-04-27 15:59:03 +03:00
id retval_handle = xamarin_get _nsobject _handle ( retval ) ;
xamarin_mono _object _release ( & retval ) ;
return retval_handle ;
2018-02-05 09:54:13 +03:00
}
2017-07-03 20:18:02 +03:00
}
void *
2021-02-11 10:18:38 +03:00
xamarin_nsstring _to _smart _enum ( id value , void * ptr , MonoClass * managedType , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
2019-11-12 23:10:16 +03:00
guint32 context_ref = GPOINTER_TO _UINT ( context ) ;
2018-02-05 09:54:13 +03:00
MonoObject * obj ;
2019-04-05 19:58:45 +03:00
if ( context_ref = = INVALID_TOKEN _REF ) {
2018-02-05 09:54:13 +03:00
// This requires the dynamic registrar to invoke the correct conversion function
2020-05-04 12:08:44 +03:00
obj = xamarin_convert _nsstring _to _smart _enum ( value , mono_type _get _object ( mono_domain _get ( ) , mono_class _get _type ( managedType ) ) , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2018-02-05 09:54:13 +03:00
return ptr ;
} 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 .
MonoMethod * managed_method ;
void * arg_ptrs [ 1 ] ;
MonoObject * exception = NULL ;
2021-04-27 15:59:03 +03:00
MonoObject * arg0 = NULL ;
2018-02-05 09:54:13 +03:00
2019-04-05 19:58:45 +03:00
managed_method = xamarin_get _managed _method _for _token ( context_ref / * token ref * / , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE ) return NULL ;
2018-02-05 09:54:13 +03:00
2021-04-27 15:59:03 +03:00
arg0 = xamarin_get _nsobject _with _type _for _ptr ( value , false , xamarin_get _parameter _type ( managed_method , 0 ) , exception_gchandle ) ;
2021-04-30 08:49:25 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE ) {
xamarin_mono _object _release ( & managed_method ) ;
return NULL ;
}
2018-02-05 09:54:13 +03:00
2021-04-27 15:59:03 +03:00
arg_ptrs [ 0 ] = arg0 ;
2018-02-05 09:54:13 +03:00
obj = mono_runtime _invoke ( managed_method , NULL , arg_ptrs , & exception ) ;
2021-04-27 15:59:03 +03:00
xamarin_mono _object _release ( & arg0 ) ;
2021-04-30 08:49:25 +03:00
xamarin_mono _object _release ( & managed_method ) ;
2021-04-27 15:59:03 +03:00
2018-02-05 09:54:13 +03:00
if ( exception ) {
2021-02-11 10:18:38 +03:00
* exception_gchandle = xamarin_gchandle _new ( exception , FALSE ) ;
2018-02-05 09:54:13 +03:00
return NULL ;
}
}
2019-11-15 18:39:38 +03:00
size_t size = ( size_t ) mono_class _value _size ( managedType , NULL ) ;
2017-07-03 20:18:02 +03:00
if ( ! ptr )
ptr = xamarin_calloc ( size ) ;
2018-02-05 09:54:13 +03:00
void * value_ptr = mono_object _unbox ( obj ) ;
2017-07-03 20:18:02 +03:00
memcpy ( ptr , value_ptr , size ) ;
2021-04-27 15:59:03 +03:00
xamarin_mono _object _release ( & obj ) ;
2017-07-03 20:18:02 +03:00
return ptr ;
}
xamarin_id _to _managed _func
2021-02-11 10:18:38 +03:00
xamarin_get _nsstring _to _smart _enum _func ( MonoClass * managedType , MonoMethod * method , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
return xamarin_nsstring _to _smart _enum ;
}
xamarin_managed _to _id _func
2021-02-11 10:18:38 +03:00
xamarin_get _smart _enum _to _nsstring _func ( MonoClass * managedType , MonoMethod * method , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
return ( xamarin_managed _to _id _func ) xamarin_smart _enum _to _nsstring ;
}
NSArray *
2021-02-11 10:18:38 +03:00
xamarin_convert _managed _to _nsarray _with _func ( MonoArray * array , xamarin_managed _to _id _func convert , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
id * buf = NULL ;
NSArray * rv = NULL ;
2019-11-15 18:39:38 +03:00
size_t element_size = 0 ;
2019-04-22 20:02:15 +03:00
char * ptr = NULL ;
2017-07-03 20:18:02 +03:00
if ( array = = NULL )
return NULL ;
2019-11-05 19:00:14 +03:00
unsigned long length = mono_array _length ( array ) ;
2017-07-03 20:18:02 +03:00
if ( length = = 0 )
return [ NSArray array ] ;
buf = ( id * ) malloc ( sizeof ( id ) * length ) ;
MonoClass * element_class = mono_class _get _element _class ( mono_object _get _class ( ( MonoObject * ) array ) ) ;
2019-04-22 20:02:15 +03:00
bool is_value _type = mono_class _is _valuetype ( element_class ) ;
if ( is_value _type ) {
2019-11-15 18:39:38 +03:00
element_size = ( size_t ) mono_class _value _size ( element_class , NULL ) ;
ptr = ( char * ) mono_array _addr _with _size ( array , ( int ) element_size , 0 ) ;
2019-04-22 20:02:15 +03:00
}
2019-11-05 19:00:14 +03:00
for ( unsigned long i = 0 ; i < length ; i + + ) {
2019-04-22 20:02:15 +03:00
MonoObject * value ;
if ( is_value _type ) {
value = mono_value _box ( mono_domain _get ( ) , element_class , ptr + element_size * i ) ;
} else {
value = mono_array _get ( array , MonoObject * , i ) ;
}
2018-02-05 09:54:13 +03:00
buf [ i ] = convert ( value , context , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE ) {
2019-04-24 09:36:50 +03:00
* exception_gchandle = xamarin_get _exception _for _element _conversion _failure ( * exception_gchandle , i ) ;
2017-07-03 20:18:02 +03:00
goto exception_handling ;
2019-04-24 09:36:50 +03:00
}
2017-07-03 20:18:02 +03:00
}
rv = [ NSArray arrayWithObjects : buf count : length ] ;
exception_handling :
free ( buf ) ;
return rv ;
}
MonoArray *
2021-02-11 10:18:38 +03:00
xamarin_convert _nsarray _to _managed _with _func ( NSArray * array , MonoClass * managedElementType , xamarin_id _to _managed _func convert , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
if ( array = = NULL )
return NULL ;
2019-11-05 19:00:14 +03:00
unsigned long length = [ array count ] ;
2017-07-03 20:18:02 +03:00
MonoArray * rv = mono_array _new ( mono_domain _get ( ) , managedElementType , length ) ;
if ( length = = 0 )
return rv ;
2019-04-22 20:02:15 +03:00
bool is_value _type = mono_class _is _valuetype ( managedElementType ) ;
MonoObject * mobj ;
2017-07-03 20:18:02 +03:00
void * valueptr = NULL ;
2019-11-15 18:39:38 +03:00
size_t element_size = 0 ;
2019-04-22 20:02:15 +03:00
char * ptr = NULL ;
if ( is_value _type ) {
2019-11-15 18:39:38 +03:00
element_size = ( size_t ) mono_class _value _size ( managedElementType , NULL ) ;
ptr = ( char * ) mono_array _addr _with _size ( rv , ( int ) element_size , 0 ) ;
2019-04-22 20:02:15 +03:00
}
2019-11-05 19:00:14 +03:00
for ( unsigned long i = 0 ; i < length ; i + + ) {
2019-04-22 20:02:15 +03:00
if ( is_value _type ) {
valueptr = convert ( [ array objectAtIndex : i ] , valueptr , managedElementType , context , exception_gchandle ) ;
memcpy ( ptr , valueptr , element_size ) ;
ptr + = element_size ;
} else {
mobj = ( MonoObject * ) convert ( [ array objectAtIndex : i ] , NULL , managedElementType , context , exception_gchandle ) ;
mono_array _setref ( rv , i , mobj ) ;
2021-04-27 15:59:03 +03:00
xamarin_mono _object _release ( & mobj ) ;
2019-04-22 20:02:15 +03:00
}
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE ) {
2019-04-24 09:36:50 +03:00
* exception_gchandle = xamarin_get _exception _for _element _conversion _failure ( * exception_gchandle , i ) ;
2017-07-03 20:18:02 +03:00
goto exception_handling ;
2019-04-24 09:36:50 +03:00
}
2017-07-03 20:18:02 +03:00
}
exception_handling :
xamarin_free ( valueptr ) ;
return rv ;
}
NSNumber *
2021-02-11 10:18:38 +03:00
xamarin_convert _managed _to _nsnumber ( MonoObject * value , MonoClass * managedType , MonoMethod * method , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
xamarin_managed _to _id _func convert = xamarin_get _managed _to _nsnumber _func ( managedType , method , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
return NULL ;
2018-02-05 09:54:13 +03:00
return convert ( value , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
}
NSValue *
2021-02-11 10:18:38 +03:00
xamarin_convert _managed _to _nsvalue ( MonoObject * value , MonoClass * managedType , MonoMethod * method , void * context , GCHandle * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
xamarin_managed _to _id _func convert = xamarin_get _managed _to _nsvalue _func ( managedType , method , exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( * exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
return NULL ;
2018-02-05 09:54:13 +03:00
return convert ( value , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
}
2021-02-11 10:18:38 +03:00
GCHandle
2017-07-03 20:18:02 +03:00
xamarin_create _bindas _exception ( MonoType * inputType , MonoType * outputType , MonoMethod * method )
{
2021-02-11 10:18:38 +03:00
GCHandle exception_gchandle ;
2017-07-03 20:18:02 +03:00
char * to_name = NULL ;
char * from_name = NULL ;
char * method_full _name = NULL ;
char * msg = NULL ;
from_name = xamarin_type _get _full _name ( inputType , & exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
to_name = xamarin_type _get _full _name ( outputType , & exception_gchandle ) ;
2021-02-11 10:18:38 +03:00
if ( exception_gchandle ! = INVALID_GCHANDLE )
2017-07-03 20:18:02 +03:00
goto exception_handling ;
method_full _name = mono_method _full _name ( method , TRUE ) ;
2018-10-04 16:43:55 +03:00
msg = xamarin_strdup _printf ( "Internal error: can't convert from '%s' to '%s' in %s. Please file a bug report with a test case (https://github.com/xamarin/xamarin-macios/issues/new)." ,
2017-07-03 20:18:02 +03:00
from_name , to_name , method_full _name ) ;
2021-02-11 10:18:38 +03:00
exception_gchandle = xamarin_gchandle _new ( ( MonoObject * ) xamarin_create _exception ( msg ) , false ) ;
2017-07-03 20:18:02 +03:00
exception_handling :
xamarin_free ( to_name ) ;
xamarin_free ( from_name ) ;
xamarin_free ( method_full _name ) ;
xamarin_free ( msg ) ;
return exception_gchandle ;
}
2019-05-06 08:26:54 +03:00
const char *
xamarin_skip _type _name ( const char * ptr )
{
const char * t = ptr ;
do {
if ( * t = = ' = ' ) {
t + + ;
return t ;
}
t + + ;
} while ( * t ! = 0 ) ;
return ptr ;
}