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
void *
2017-07-03 20:18:02 +03:00
xamarin_marshal _return _value ( MonoType * mtype , const char * type , MonoObject * retval , bool retain , MonoMethod * method , MethodDescription * desc , guint32 * 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 :
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 _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 ) ) {
Optimize calls to BlockLiteral.SetupBlock to inject the block signature. (#3391)
* [linker] Optimize calls to BlockLiteral.SetupBlock to inject the block signature.
Optimize calls to BlockLiteral.SetupBlock[Unsafe] to calculate the block
signature at build time, and inject it into the call site.
This makes block invocations 10-15x faster (I've added tests that asserts at
least an 8x increase).
It's also required in order to be able to remove the dynamic registrar code in
the future (since calculating the block signature at runtime requires the
dynamic registrar).
* [mtouch/mmp] Add support for reporting errors/warnings that point to the code line causing the error/warning.
Add support for reporting errors/warnings that point to the code line causing
the error/warning by adding ErrorHelper overloads that take the exact
instruction to report (previously we defaulted to the first line/instruction
in a method).
* [tests] Add support for asserting filename/linenumber in warning messages.
* Make all methods that manually create BlockLiterals optimizable.
* [tests] Create a BaseOptimizeGeneratedCodeTest test that's included in both XI's and XM's link all test.
* [tests] Add link all test (for both XI and XM) to test the BlockLiteral.SetupBlock optimization.
* [tests] Add mtouch/mmp tests for the BlockLiteral.SetupBlock optimization.
* [tests][linker] Make the base test class abstract, so tests in the base class aren't executed twice.
* [tests][linker] Don't execute linkall-only tests in linksdk.
The optimization tests only apply when the test assembly is linked, and that
only happens in linkall, so exclude those tests in linksdk.
* [tests][mmptest] Update test according to mmp changes.
Fixes these test failures:
1) Failed : Xamarin.MMP.Tests.MMPTests.MM0132("inline-runtime-arch")
The warning 'MM0132: Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' was not found in the output:
Message #1 did not match:
actual: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
expected: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'
Message #2 did not match:
actual: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
expected: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'
2) Failed : Xamarin.MMP.Tests.MMPTests.MM0132("foo")
The warning 'MM0132: Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' was not found in the output:
Message #1 did not match:
actual: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
expected: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'
Message #2 did not match:
actual: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
expected: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'
* [tests][linker] Fix typo.
Fixes this test failure:
1) SetupBlock_CustomDelegate (Linker.Shared.BaseOptimizeGeneratedCodeTest.SetupBlock_CustomDelegate)
Counter
Expected: 1
But was: 2
* [registrar] Minor adjustment to error message to match previous (and better) behavior.
Fixes this test failure:
1) Failed : Xamarin.Registrar.GenericType_WithInvalidParameterTypes
The error 'MT4136: The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<U>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)'' was not found in the output:
Message #1 did not match:
actual: 'The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<Foundation.NSObject>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)''
expected: 'The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<U>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)''
* [docs] mmp shows MM errors/warnings.
* [docs] Improve according to reviews.
* [tests] Fix merge failure causing test duplication.
2018-02-06 09:08:15 +03:00
return xamarin_get _block _for _delegate ( method , retval , NULL , 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
if ( desc && desc -> bindas [ 0 ] . original_type ! = NULL ) {
2018-02-05 09:54:13 +03:00
return xamarin_generate _conversion _to _native ( retval , mono_class _get _type ( r_klass ) , mono_reflection _type _get _type ( desc -> bindas [ 0 ] . original_type ) , method , INVALID_TOKEN _REF , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
} else if ( r_klass = = mono_get _string _class ( ) ) {
2016-04-21 15:19:32 +03:00
char * str = mono_string _to _utf8 ( ( MonoString * ) retval ) ;
NSString * rv = [ [ NSString alloc ] initWithUTF8String : str ] ;
if ( ! retain )
[ rv autorelease ] ;
mono_free ( str ) ;
return ( void * ) rv ;
} else if ( xamarin_is _class _array ( r_klass ) ) {
MonoClass * e_klass = mono_class _get _element _class ( r_klass ) ;
bool is_string = e_klass = = mono_get _string _class ( ) ;
MonoArray * m_arr = ( MonoArray * ) retval ;
int length = mono_array _length ( m_arr ) ;
2017-02-20 21:29:13 +03:00
id * buf = ( id * ) malloc ( sizeof ( id ) * length ) ;
2016-04-21 15:19:32 +03:00
NSArray * arr ;
int i ;
id v ;
for ( i = 0 ; i < length ; i + + ) {
MonoObject * value = mono_array _get ( m_arr , MonoObject * , i ) ;
if ( is_string ) {
char * str = mono_string _to _utf8 ( ( MonoString * ) value ) ;
NSString * sv = [ [ NSString alloc ] initWithUTF8String : str ] ;
[ sv autorelease ] ;
mono_free ( str ) ;
v = sv ;
} else {
2016-06-02 13:18:45 +03:00
v = xamarin_get _handle ( value , exception_gchandle ) ;
2017-02-20 21:35:40 +03:00
if ( * exception_gchandle ! = 0 ) {
free ( buf ) ;
2016-06-02 13:18:45 +03:00
return NULL ;
2017-02-20 21:35:40 +03:00
}
2016-04-21 15:19:32 +03:00
}
buf [ i ] = v ;
}
arr = [ [ NSArray alloc ] initWithObjects : buf count : length ] ;
free ( buf ) ;
if ( ! retain )
[ arr autorelease ] ;
return ( void * ) arr ;
} else if ( xamarin_is _class _nsobject ( r_klass ) ) {
2016-06-02 13:18:45 +03:00
id i = xamarin_get _handle ( retval , exception_gchandle ) ;
if ( * exception_gchandle ! = 0 )
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 {
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 http://bugzilla.xamarin.com\n" , mono_class _get _namespace ( r_klass ) , mono_class _get _name ( r_klass ) ) ;
}
}
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 ) ;
}
}
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 :
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 ;
}
2016-04-21 15:19:32 +03:00
int
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 .
int length = 0 ;
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 .
fprintf ( stderr , PRODUCT ": Failed to calculate the frame size for the method [%s %s] (%s). Using a value of %i instead.\n" , class_getName ( cls ) , sel_getName ( sel ) , [ [ ex description ] UTF8String ] , length ) ;
}
} 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 ) ;
int min_length = 0 ;
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 + + )
min_length = min_length * 10 + ( min_start [ i ] - ' 0 ' ) ;
}
}
// 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 ) {
int tl = xamarin_objc _type _size ( desc ) ;
// 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
2016-05-12 12:36:36 +03:00
return 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 ) ;
return objc_msgSendSuper ( & sup , sel ) ;
}
# 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 ;
int gchandle ;
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
gchandle = xamarin_get _gchandle _with _flags ( self ) ;
if ( gchandle ! = 0 )
xamarin_set _gchandle ( self , 0 ) ;
// 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
if ( gchandle ! = 0 )
xamarin_set _gchandle ( self , gchandle ) ;
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 ;
int gchandle ;
# 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
gchandle = xamarin_get _gchandle _with _flags ( self ) ;
if ( gchandle ! = 0 )
xamarin_set _gchandle ( self , 0 ) ;
// Call the managed implementation
id (*invoke) (id, SEL, NSZone*) = ( id (*)(id, SEL, NSZone*) ) xamarin_trampoline ;
rv = invoke ( self , sel , zone ) ;
// Restore our GCHandle
if ( gchandle ! = 0 )
xamarin_set _gchandle ( self , gchandle ) ;
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 ) .
MONO_ASSERT _GC _SAFE ;
2016-04-21 15:19:32 +03:00
int ref_count ;
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
xamarin_notify _dealloc ( id self , int gchandle )
{
2016-06-02 13:18:45 +03:00
guint32 exception_gchandle = 0 ;
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 * /
MonoObject * mobj = mono_gchandle _get _target ( gchandle ) ;
# if defined ( DEBUG_REF _COUNTING )
2016-09-06 23:55:23 +03:00
PRINT ( "xamarin_notify_dealloc (%p, %i) target: %p\n" , self , gchandle , mobj ) ;
2016-04-21 15:19:32 +03:00
# endif
xamarin_free _gchandle ( self , gchandle ) ;
2016-06-02 13:18:45 +03:00
xamarin_unregister _nsobject ( self , mobj , & exception_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 .
MONO_ASSERT _GC _SAFE ;
2016-04-21 15:19:32 +03:00
pthread_mutex _lock ( & refcount_mutex ) ;
# if defined ( DEBUG_REF _COUNTING )
int ref_count = [ self retainCount ] ;
bool had_managed _ref = xamarin_has _managed _ref ( self ) ;
int pre_gchandle = xamarin_get _gchandle ( self ) ;
# 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 ;
static const char * associated_key = "x" ; // the string value doesn ' t matter , only the pointer value .
void
xamarin_set _gchandle _trampoline ( id self , SEL sel , int gc_handle )
{
2016-02-15 21:02:14 +03:00
// COOP : Called by ObjC ( when the setGCHandle : selector is called on an object ) .
// 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 ) ;
if ( obj = = NULL && gc_handle ! = 0 ) {
obj = [ [ XamarinAssociatedObject alloc ] init ] ;
obj -> gc_handle = gc_handle ;
obj -> native_object = self ;
objc_setAssociatedObject ( self , associated_key , obj , OBJC_ASSOCIATION _RETAIN _NONATOMIC ) ;
[ obj release ] ;
}
if ( obj ! = NULL )
obj -> gc_handle = gc_handle ;
pthread_mutex _lock ( & gchandle_hash _lock ) ;
if ( gchandle_hash = = NULL )
gchandle_hash = CFDictionaryCreateMutable ( kCFAllocatorDefault , 0 , NULL , NULL ) ;
if ( gc_handle = = 0 ) {
CFDictionaryRemoveValue ( gchandle_hash , self ) ;
} else {
CFDictionarySetValue ( gchandle_hash , self , GINT_TO _POINTER ( gc_handle ) ) ;
}
pthread_mutex _unlock ( & gchandle_hash _lock ) ;
}
int
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 * /
int gc_handle = 0 ;
pthread_mutex _lock ( & gchandle_hash _lock ) ;
if ( gchandle_hash ! = NULL )
gc_handle = GPOINTER_TO _INT ( CFDictionaryGetValue ( gchandle_hash , self ) ) ;
pthread_mutex _unlock ( & gchandle_hash _lock ) ;
return gc_handle ;
}
2017-07-03 20:18:02 +03:00
id
2018-02-05 09:54:13 +03:00
xamarin_generate _conversion _to _native ( MonoObject * value , MonoType * inputType , MonoType * outputType , MonoMethod * method , guint32 context , guint32 * 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 ) ;
if ( * exception_gchandle ! = 0 )
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 ;
}
if ( * exception_gchandle ! = 0 )
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 ) ;
2017-07-03 20:18:02 +03:00
if ( * exception_gchandle ! = 0 )
goto exception_handling ;
} else {
2018-02-05 09:54:13 +03:00
convertedValue = func ( value , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
if ( * exception_gchandle ! = 0 )
goto exception_handling ;
}
}
exception_handling :
return convertedValue ;
}
void *
2018-02-05 09:54:13 +03:00
xamarin_generate _conversion _to _managed ( id value , MonoType * inputType , MonoType * outputType , MonoMethod * method , guint32 * exception_gchandle , guint32 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 ) ;
if ( * exception_gchandle ! = 0 )
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 ;
}
if ( * exception_gchandle ! = 0 )
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 ) ;
2017-07-03 20:18:02 +03:00
if ( * exception_gchandle ! = 0 )
goto exception_handling ;
} else {
2018-02-05 09:54:13 +03:00
convertedValue = func ( value , NULL , underlyingManagedType , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
if ( * exception_gchandle ! = 0 )
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 .
2018-02-05 09:54:13 +03:00
void * xamarin_nsnumber _to _bool ( NSNumber * number , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsnumber _to _nfloat ( NSNumber * number , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsnumber _to _nfloat ( NSNumber * number , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 .
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _nsrange ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 .
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _cgaffinetransform ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _catransform3d ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 .
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _cllocationcoordinate2d ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _cmtime ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 , guint32 context , guint32 * 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 , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _mkcoordinatespan ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _scnmatrix4 ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 *
2018-02-05 09:54:13 +03:00
xamarin_nsvalue _to _scnvector3 ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 ;
}
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _scnvector4 ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
void * xamarin_nsvalue _to _uiedgeinsets ( NSValue * value , void * ptr , MonoClass * managedType , guint32 context , guint32 * 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 , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
id xamarin_bool _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithBool : * ( BOOL * ) mono_object _unbox ( value ) ] ; }
id xamarin_sbyte _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithChar : * ( int8_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_byte _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithUnsignedChar : * ( uint8_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_short _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithShort : * ( int16_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_ushort _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithUnsignedShort : * ( uint16_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_int _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithInt : * ( int32_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_uint _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithUnsignedInt : * ( uint32_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_long _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithLongLong : * ( int64_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_ulong _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithUnsignedLongLong : * ( uint64_t * ) mono_object _unbox ( value ) ] ; }
id xamarin_nint _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithInteger : * ( NSInteger * ) mono_object _unbox ( value ) ] ; }
id xamarin_nuint _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithUnsignedInteger : * ( NSUInteger * ) mono_object _unbox ( value ) ] ; }
id xamarin_float _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithFloat : * ( float * ) mono_object _unbox ( value ) ] ; }
id xamarin_double _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithDouble : * ( double * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# if __POINTER _WIDTH __ = = 32
2018-02-05 09:54:13 +03:00
id xamarin_nfloat _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithFloat : * ( float * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# elif __POINTER _WIDTH __ = = 64
2018-02-05 09:54:13 +03:00
id xamarin_nfloat _to _nsnumber ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSNumber numberWithDouble : * ( double * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# else
# error Invalid pointer size .
# endif
2018-02-05 09:54:13 +03:00
id xamarin_nsrange _to _nsvalue ( MonoObject * value , guint32 context , guint32 * 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
2018-02-05 09:54:13 +03:00
id xamarin_cgaffinetransform _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCGAffineTransform : * ( CGAffineTransform * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgpoint _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCGPoint : * ( CGPoint * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgrect _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCGRect : * ( CGRect * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgsize _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCGSize : * ( CGSize * ) mono_object _unbox ( value ) ] ; }
id xamarin_cgvector _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCGVector : * ( CGVector * ) mono_object _unbox ( value ) ] ; }
id xamarin_nsdirectionaledgeinsets _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithDirectionalEdgeInsets : * ( NSDirectionalEdgeInsets * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREANIMATION
2018-02-05 09:54:13 +03:00
id xamarin_catransform3d _to _nsvalue ( MonoObject * value , guint32 context , guint32 * 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 .
2018-02-05 09:54:13 +03:00
id xamarin_cllocationcoordinate2d _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithMKCoordinate : * ( CLLocationCoordinate2D * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_COREMEDIA
2018-02-05 09:54:13 +03:00
id xamarin_cmtime _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCMTime : * ( CMTime * ) mono_object _unbox ( value ) ] ; }
id xamarin_cmtimemapping _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCMTimeMapping : * ( CMTimeMapping * ) mono_object _unbox ( value ) ] ; }
id xamarin_cmtimerange _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithCMTimeRange : * ( CMTimeRange * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
# if HAVE_MAPKIT
2018-02-05 09:54:13 +03:00
id xamarin_mkcoordinatespan _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithMKCoordinateSpan : * ( MKCoordinateSpan * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# endif
2018-02-05 09:54:13 +03:00
id xamarin_scnmatrix4 _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithSCNMatrix4 : * ( SCNMatrix4 * ) mono_object _unbox ( value ) ] ; }
id xamarin_scnvector3 _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithSCNVector3 : * ( SCNVector3 * ) mono_object _unbox ( value ) ] ; }
id xamarin_scnvector4 _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithSCNVector4 : * ( SCNVector4 * ) mono_object _unbox ( value ) ] ; }
2017-07-03 20:18:02 +03:00
# if HAVE_UIKIT
2018-02-05 09:54:13 +03:00
id xamarin_uiedgeinsets _to _nsvalue ( MonoObject * value , guint32 context , guint32 * exception_gchandle ) { return [ NSValue valueWithUIEdgeInsets : * ( UIEdgeInsets * ) mono_object _unbox ( value ) ] ; }
id xamarin_uioffset _to _nsvalue ( MonoObject * value , guint32 context , guint32 * 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
2017-07-03 20:18:02 +03:00
static void *
xamarin_get _nsnumber _converter ( MonoClass * managedType , MonoMethod * method , bool to_managed , guint32 * exception_gchandle )
{
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 ) ;
if ( * exception_gchandle ! = 0 )
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 *
xamarin_get _nsvalue _converter ( MonoClass * managedType , MonoMethod * method , bool to_managed , guint32 * exception_gchandle )
{
void * func = NULL ;
char * fullname = xamarin_class _get _full _name ( managedType , exception_gchandle ) ;
if ( * exception_gchandle ! = 0 )
goto exception_handling ;
# if MONOMAC
2017-07-11 10:48:56 +03:00
if ( xamarin_use _new _assemblies && ! strncmp ( fullname , "MonoMac." , 8 ) )
memmove ( fullname , fullname + 8 , strlen ( fullname ) - 7 / * also copy the null char * / ) ;
2017-07-03 20:18:02 +03:00
# endif
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
xamarin_get _nsnumber _to _managed _func ( MonoClass * managedType , MonoMethod * method , guint32 * exception_gchandle )
{
return ( xamarin_id _to _managed _func ) xamarin_get _nsnumber _converter ( managedType , method , true , exception_gchandle ) ;
}
xamarin_managed _to _id _func
xamarin_get _managed _to _nsnumber _func ( MonoClass * managedType , MonoMethod * method , guint32 * exception_gchandle )
{
return ( xamarin_managed _to _id _func ) xamarin_get _nsnumber _converter ( managedType , method , false , exception_gchandle ) ;
}
xamarin_id _to _managed _func
xamarin_get _nsvalue _to _managed _func ( MonoClass * managedType , MonoMethod * method , guint32 * exception_gchandle )
{
return ( xamarin_id _to _managed _func ) xamarin_get _nsvalue _converter ( managedType , method , true , exception_gchandle ) ;
}
xamarin_managed _to _id _func
xamarin_get _managed _to _nsvalue _func ( MonoClass * managedType , MonoMethod * method , guint32 * exception_gchandle )
{
return ( xamarin_managed _to _id _func ) xamarin_get _nsvalue _converter ( managedType , method , false , exception_gchandle ) ;
}
void *
2018-02-05 09:54:13 +03:00
xamarin_smart _enum _to _nsstring ( MonoObject * value , guint32 context / * token ref * / , guint32 * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
2018-02-05 09:54:13 +03:00
if ( context = = INVALID_TOKEN _REF ) {
// This requires the dynamic registrar to invoke the correct conversion function
int handle = mono_gchandle _new ( value , FALSE ) ;
NSString * rv = xamarin_convert _smart _enum _to _nsstring ( GINT_TO _POINTER ( handle ) , exception_gchandle ) ;
mono_gchandle _free ( handle ) ;
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 ] ;
managed_method = xamarin_get _managed _method _for _token ( context / * token ref * / , exception_gchandle ) ;
if ( * exception_gchandle ! = 0 ) return NULL ;
arg_ptrs [ 0 ] = mono_object _unbox ( value ) ;
retval = mono_runtime _invoke ( managed_method , NULL , arg_ptrs , & exception ) ;
if ( exception ) {
* exception_gchandle = mono_gchandle _new ( exception , FALSE ) ;
return NULL ;
}
if ( retval = = NULL )
return NULL ;
return xamarin_get _nsobject _handle ( retval ) ;
}
2017-07-03 20:18:02 +03:00
}
void *
2018-02-05 09:54:13 +03:00
xamarin_nsstring _to _smart _enum ( id value , void * ptr , MonoClass * managedType , guint32 context , guint32 * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
2018-02-05 09:54:13 +03:00
int gc_handle = 0 ;
MonoObject * obj ;
if ( context = = INVALID_TOKEN _REF ) {
// This requires the dynamic registrar to invoke the correct conversion function
void * rv = xamarin_convert _nsstring _to _smart _enum ( value , mono_type _get _object ( mono_domain _get ( ) , mono_class _get _type ( managedType ) ) , exception_gchandle ) ;
if ( * exception_gchandle ! = 0 )
return ptr ;
gc_handle = GPOINTER_TO _INT ( rv ) ;
obj = mono_gchandle _get _target ( gc_handle ) ;
} else {
// The static registrar found the correct conversion function , and provided a token ref we can use
// to find it ( and invoke it ) , without needing the dynamic registrar .
MonoMethod * managed_method ;
void * arg_ptrs [ 1 ] ;
MonoObject * exception = NULL ;
managed_method = xamarin_get _managed _method _for _token ( context / * token ref * / , exception_gchandle ) ;
if ( * exception_gchandle ! = 0 ) return NULL ;
arg_ptrs [ 0 ] = xamarin_get _nsobject _with _type _for _ptr ( value , false , xamarin_get _parameter _type ( managed_method , 0 ) , exception_gchandle ) ;
if ( * exception_gchandle ! = 0 ) return NULL ;
obj = mono_runtime _invoke ( managed_method , NULL , arg_ptrs , & exception ) ;
if ( exception ) {
* exception_gchandle = mono_gchandle _new ( exception , FALSE ) ;
return NULL ;
}
}
2017-07-03 20:18:02 +03:00
int size = mono_class _value _size ( managedType , NULL ) ;
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 ) ;
2018-02-05 09:54:13 +03:00
if ( context = = INVALID_TOKEN _REF )
mono_gchandle _free ( gc_handle ) ;
2017-07-03 20:18:02 +03:00
return ptr ;
}
xamarin_id _to _managed _func
xamarin_get _nsstring _to _smart _enum _func ( MonoClass * managedType , MonoMethod * method , guint32 * exception_gchandle )
{
return xamarin_nsstring _to _smart _enum ;
}
xamarin_managed _to _id _func
xamarin_get _smart _enum _to _nsstring _func ( MonoClass * managedType , MonoMethod * method , guint32 * exception_gchandle )
{
return ( xamarin_managed _to _id _func ) xamarin_smart _enum _to _nsstring ;
}
NSArray *
2018-02-05 09:54:13 +03:00
xamarin_convert _managed _to _nsarray _with _func ( MonoArray * array , xamarin_managed _to _id _func convert , guint32 context , guint32 * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
id * buf = NULL ;
NSArray * rv = NULL ;
if ( array = = NULL )
return NULL ;
int length = mono_array _length ( array ) ;
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 ) ) ;
int element_size = mono_class _value _size ( element_class , NULL ) ;
char * ptr = ( char * ) mono_array _addr _with _size ( array , element_size , 0 ) ;
for ( int i = 0 ; i < length ; i + + ) {
MonoObject * value = mono_value _box ( mono_domain _get ( ) , element_class , ptr + element_size * i ) ;
2018-02-05 09:54:13 +03:00
buf [ i ] = convert ( value , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
if ( * exception_gchandle ! = 0 )
goto exception_handling ;
}
rv = [ NSArray arrayWithObjects : buf count : length ] ;
exception_handling :
free ( buf ) ;
return rv ;
}
MonoArray *
2018-02-05 09:54:13 +03:00
xamarin_convert _nsarray _to _managed _with _func ( NSArray * array , MonoClass * managedElementType , xamarin_id _to _managed _func convert , guint32 context , guint32 * exception_gchandle )
2017-07-03 20:18:02 +03:00
{
if ( array = = NULL )
return NULL ;
int length = [ array count ] ;
MonoArray * rv = mono_array _new ( mono_domain _get ( ) , managedElementType , length ) ;
if ( length = = 0 )
return rv ;
void * valueptr = NULL ;
int element_size = mono_class _value _size ( managedElementType , NULL ) ;
char * ptr = ( char * ) mono_array _addr _with _size ( rv , element_size , 0 ) ;
for ( int i = 0 ; i < length ; i + + ) {
2018-02-05 09:54:13 +03:00
valueptr = convert ( [ array objectAtIndex : i ] , valueptr , managedElementType , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
if ( * exception_gchandle ! = 0 )
goto exception_handling ;
memcpy ( ptr , valueptr , element_size ) ;
ptr + = element_size ;
}
exception_handling :
xamarin_free ( valueptr ) ;
return rv ;
}
NSNumber *
2018-02-05 09:54:13 +03:00
xamarin_convert _managed _to _nsnumber ( MonoObject * value , MonoClass * managedType , MonoMethod * method , guint32 context , guint32 * 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 ) ;
if ( * exception_gchandle ! = 0 )
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 *
2018-02-05 09:54:13 +03:00
xamarin_convert _managed _to _nsvalue ( MonoObject * value , MonoClass * managedType , MonoMethod * method , guint32 context , guint32 * 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 ) ;
if ( * exception_gchandle ! = 0 )
return NULL ;
2018-02-05 09:54:13 +03:00
return convert ( value , context , exception_gchandle ) ;
2017-07-03 20:18:02 +03:00
}
guint32
xamarin_create _bindas _exception ( MonoType * inputType , MonoType * outputType , MonoMethod * method )
{
guint32 exception_gchandle ;
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 ) ;
if ( exception_gchandle ! = 0 )
goto exception_handling ;
to_name = xamarin_type _get _full _name ( outputType , & exception_gchandle ) ;
if ( exception_gchandle ! = 0 )
goto exception_handling ;
method_full _name = mono_method _full _name ( method , TRUE ) ;
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://bugzilla.xamarin.com)." ,
from_name , to_name , method_full _name ) ;
exception_gchandle = mono_gchandle _new ( ( MonoObject * ) xamarin_create _exception ( msg ) , false ) ;
exception_handling :
xamarin_free ( to_name ) ;
xamarin_free ( from_name ) ;
xamarin_free ( method_full _name ) ;
xamarin_free ( msg ) ;
return exception_gchandle ;
}