2021-03-18 09:23:39 +03:00
/ * - * - Mode : C ; tab - width : 8 ; indent - tabs - mode : t ; c - basic - offset : 8 - * - * /
/ *
* Authors : Rolf Bjarne Kvinge
*
* Copyright ( C ) 2021 Microsoft Corp .
*
* /
# if defined ( CORECLR_RUNTIME )
2021-07-16 17:15:17 +03:00
# include < sys / stat . h >
2021-05-12 16:21:56 +03:00
# include < inttypes . h >
2021-06-01 08:36:01 +03:00
# include < pthread . h >
2023-06-21 21:49:49 +03:00
# include < sys / mman . h >
2021-05-12 16:21:56 +03:00
2021-03-25 09:25:20 +03:00
# include "product.h"
2021-05-25 09:19:27 +03:00
# include "runtime-internal.h"
2021-06-01 08:36:01 +03:00
# include "slinked-list.h"
2021-03-18 09:23:39 +03:00
# include "xamarin/xamarin.h"
# include "xamarin/coreclr-bridge.h"
2021-03-22 10:04:56 +03:00
# include "coreclrhost.h"
unsigned int coreclr_domainId = 0 ;
void * coreclr_handle = NULL ;
2021-06-01 08:36:01 +03:00
pthread_mutex _t monoobject_lock = PTHREAD_MUTEX _INITIALIZER ;
SList * release_at _exit = NULL ; // A list of MonoObject * s to be released at process exit
2021-03-22 10:04:56 +03:00
2021-05-25 09:19:27 +03:00
# if defined ( TRACK_MONOOBJECTS )
// To enable tracking of MonoObject * instances , uncomment the TRACK_MONOOBJECTS define in :
// * runtime / runtime - internal . h
// * src / ObjCRuntime / Runtime . CoreCLR . cs
// Both defines must be uncommented for tracking to work . Once enabled , you can opt - in to
// capturing the stack trace of when the MonoObject * was created , by setting the
// MONOOBJECT_TRACKING _WITH _STACKTRACES environment variable .
# include < execinfo . h >
static int _Atomic monoobject_created = 0 ;
static int _Atomic monoobject_destroyed = 0 ;
static CFMutableDictionaryRef monoobject_dict = NULL ;
struct monoobject_tracked _entry {
char * managed ;
void * addresses [ 128 ] ;
int frames ;
char * native ;
} ;
static char *
get_stacktrace ( void * * addresses , int frames )
{
// get the symbols for the addresses
char * * strs = backtrace_symbols ( addresses , frames ) ;
// compute the total length of all the symbols , adding 1 for every line ( for the newline )
size_t length = 0 ;
int i ;
for ( i = 0 ; i < frames ; i + + )
length + = strlen ( strs [ i ] ) + 1 ;
length + + ;
// format the symbols as one long string with newlines
char * rv = ( char * ) calloc ( 1 , length ) ;
char * buffer = rv ;
size_t left = length ;
for ( i = 0 ; i < frames ; i + + ) {
snprintf ( buffer , left , "%s\n" , strs [ i ] ) ;
size_t slen = strlen ( strs [ i ] ) + 1 ;
left - = slen ;
buffer + = slen ;
}
free ( strs ) ;
return rv ;
}
void
xamarin_bridge _log _monoobject ( MonoObject * mobj , const char * stacktrace )
{
// add stack traces if we have them / they ' ve been been requested
if ( monoobject_dict ! = NULL ) {
// create a new entry
struct monoobject_tracked _entry * value = ( struct monoobject_tracked _entry * ) calloc ( 1 , sizeof ( struct monoobject_tracked _entry ) ) ;
value -> managed = stacktrace ? xamarin_strdup _printf ( "%s" , stacktrace ) : NULL ;
value -> frames = backtrace ( ( void * * ) & value -> addresses , sizeof ( value -> addresses ) / sizeof ( & value -> addresses [ 0 ] ) ) ;
// insert into our dictionary of monoobjects
pthread_mutex _lock ( & monoobject_lock ) ;
CFDictionarySetValue ( monoobject_dict , mobj , value ) ;
pthread_mutex _unlock ( & monoobject_lock ) ;
}
atomic_fetch _add ( & monoobject_created , 1 ) ;
}
void
xamarin_bridge _dump _monoobjects ( )
{
if ( monoobject_dict ! = NULL ) {
// dump the monoobject ' s that haven ' t been freed ( max 10 entries ) .
pthread_mutex _lock ( & monoobject_lock ) ;
// get the keys and values
unsigned int length = ( unsigned int ) CFDictionaryGetCount ( monoobject_dict ) ;
MonoObject * * keys = ( MonoObject * * ) calloc ( 1 , sizeof ( void * ) * length ) ;
char * * values = ( char * * ) calloc ( 1 , sizeof ( char * ) * length ) ;
CFDictionaryGetKeysAndValues ( monoobject_dict , ( const void * * ) keys , ( const void * * ) values ) ;
// is there anything left in the dictionary ? if so , show that
unsigned int items_to _show = length > 10 ? 10 : length ;
if ( items_to _show > 0 ) {
fprintf ( stderr , "⚠️ There were %i MonoObjects created, %i MonoObjects freed, so %i were not freed.\n" , ( int ) monoobject_created , ( int ) monoobject_destroyed , ( int ) ( monoobject_created - monoobject_destroyed ) ) ;
fprintf ( stderr , "Showing the first %i (of %i) MonoObjects:\n" , items_to _show , length ) ;
for ( unsigned int i = 0 ; i < items_to _show ; i + + ) {
MonoObject * obj = keys [ i ] ;
struct monoobject_tracked _entry * value = ( struct monoobject_tracked _entry * ) values [ i ] ;
2021-06-01 21:43:50 +03:00
char * fullname = xamarin_get _object _type _fullname ( obj -> gchandle ) ;
fprintf ( stderr , "Object %i/%i %p RC: %i Type: %s\n" , i + 1 , ( int ) length , obj , ( int ) obj -> reference_count , fullname ) ;
xamarin_free ( fullname ) ;
2021-05-25 09:19:27 +03:00
if ( value -> managed && * value -> managed )
fprintf ( stderr , "\tManaged stack trace:\n%s\n" , value -> managed ) ;
if ( value -> native = = NULL && value -> frames > 0 )
value -> native = get_stacktrace ( value -> addresses , value -> frames ) ;
if ( value -> native && * value -> native )
fprintf ( stderr , "\tNative stack trace:\n%s\n" , value -> native ) ;
}
fprintf ( stderr , "⚠️ There were %i MonoObjects created, %i MonoObjects freed, so %i were not freed.\n" , ( int ) monoobject_created , ( int ) monoobject_destroyed , ( int ) ( monoobject_created - monoobject_destroyed ) ) ;
} else {
fprintf ( stderr , "✅ There were %i MonoObjects created, %i MonoObjects freed, so no leaked MonoObjects.\n" , ( int ) monoobject_created , ( int ) monoobject_destroyed ) ;
}
pthread_mutex _unlock ( & monoobject_lock ) ;
free ( keys ) ;
free ( values ) ;
} else {
fprintf ( stderr , "There were %i MonoObjects created, %i MonoObjects freed, so %i were not freed.\n" , ( int ) monoobject_created , ( int ) monoobject_destroyed , ( int ) ( monoobject_created - monoobject_destroyed ) ) ;
}
}
static void
monoobject_dict _free _value ( CFAllocatorRef allocator , const void * value )
{
struct monoobject_tracked _entry * v = ( struct monoobject_tracked _entry * ) value ;
xamarin_free ( v -> managed ) ;
if ( v -> native )
free ( v -> native ) ;
free ( v ) ;
}
# endif // defined ( TRACK_MONOOBJECTS )
2021-06-02 01:13:49 +03:00
/ *
* Toggle - ref support for CoreCLR is a bit different than for MonoVM . It goes like this :
*
* 1 ) We have to opt - in for the required GC support by calling
* ObjectiveCMarshal . Initialize ( in managed code ) at startup . This happens
* in Runtime . InitializeCoreCLRBridge ( in Runtime . CoreCLR . cs ) .
*
* 2 ) Types that can be toggled , must have the [ ObjectiveCTrackedType ]
* attribute ( on any subclass ) . We put this attribute on NSObject .
*
* 3 ) We have to call ObjectiveCMarshal . CreateReferenceTrackingHandle when an
* object is toggled . This callback returns a GCHandle for the managed
* object , and a pointer to native memory ( size : 2 pointers ) where we can
* store whatever we want . We store the native Handle , and the Flags
* property . Unfortunately this means duplicating information , and we have
* to make sure they ' re in sync . It didn ' t see a sane way around this
* though , because we need the Handle and the Flags somewhere accessible
* from native code during the GC ( so we can ' t store them in managed
* memory ) , while at the same time we don ' t want to create an additional
* native block of memory for every NSObject , nor use some complex logic to
* support either a managed or a native storage . With the current solution
* we ' re only using additional native memory for toggled objects .
* Additionally , updates have to flow :
*
* a ) From managed to native for Handle and Flags , so we update the native
* memory ( if it ' s there ) when the Handle or Flags properties are set .
* b ) From native to managed for a single flag value
* ( NSObjectFlagsInFinalizerQueue ) , which we fetch in managed code in
* the Flags getter .
*
2022-04-21 09:22:24 +03:00
* Note : we call ObjectiveCMarshal . CreateReferenceTrackingHandle for all
* NSObjects , not only toggled ones , because we need point 5 ) below to
* happen for all NSObjects , not just toggled ones .
*
2021-06-02 01:13:49 +03:00
* 4 ) The CoreCLR GC will invoke a callback we installed when calling
* ObjectiveCMarshal . Initialize to check if that toggled managed object can
* be collected or not . This callback is executed during the GC , which
* means it ' s very limited what we can do safely : but we can read and write
* to the memory given to us when the managed object was toggled , which is
* why we store the Handle and the Flags property - that ' s what we need to
* know to determine whether the managed object can be collected or not .
*
* 5 ) When the managed object is finalized , the GC will invoke another
* callback ( xamarin_coreclr _reference _tracking _tracked _object _entered _finalization )
* to let us know , and we ' ll set the corresponding flag in the flags
*
* 6 ) Finally , the GCHandle we got in step 3 ) is freed when the managed peer
2022-04-21 09:22:24 +03:00
* is freed and removed from our object map .
2021-06-02 01:13:49 +03:00
*
* Caveat : we don ' t support the server GC ( because it uses multiple threads ,
* and thus may call xamarin_coreclr _reference _tracking _begin _end _callback
* from multiple threads for the same garbage collection , which we don ' t
* support right now - but it may be possible to implement by using a
* different lock in xamarin_gc _event ) .
*
* Ref : https : // github . com / dotnet / runtime / issues / 44659
* Ref : https : // github . com / dotnet / designs / blob / 1 bb5844c165195e2f633cb1dbe042c4b92aefc4d / accepted / 2021 / objectivec - interop . md
* /
struct TrackedObjectInfo {
id handle ;
enum NSObjectFlags flags ;
} ;
2021-03-18 09:23:39 +03:00
void
xamarin_bridge _setup ( )
{
}
void
xamarin_bridge _initialize ( )
{
2021-05-25 09:19:27 +03:00
# if defined ( TRACK_MONOOBJECTS )
// Only capture the stack trace if requested explicitly , it has a very significant perf hit ( monotouch - test is 3 x slower ) .
const char * with_stacktraces = getenv ( "MONOOBJECT_TRACKING_WITH_STACKTRACES" ) ;
if ( with_stacktraces && * with_stacktraces ) {
// Create a dictionary to store the stack traces
CFDictionaryValueCallBacks value_callbacks = { 0 } ;
value_callbacks . release = monoobject_dict _free _value ;
monoobject_dict = CFDictionaryCreateMutable ( kCFAllocatorDefault , 0 , NULL , & value_callbacks ) ;
fprintf ( stderr , "Stack traces enabled for MonoObject tracking.\n" ) ;
}
# endif // defined ( TRACK_MONOOBJECTS )
}
void
xamarin_bridge _shutdown ( )
{
2021-06-01 08:36:01 +03:00
SList * list ;
// Free our list of MonoObject * s to free at process exist .
// No need to keep the lock locked while we traverse the list , the only thing we need to protect
// are reads and writes to the ' release_at _exit ' variable , so let ' s do just that .
pthread_mutex _lock ( & monoobject_lock ) ;
list = release_at _exit ;
release_at _exit = NULL ;
pthread_mutex _unlock ( & monoobject_lock ) ;
while ( list ) {
xamarin_mono _object _release ( ( MonoObject * * ) & list -> data ) ;
list = list -> next ;
}
s_list _free ( list ) ;
2021-05-25 09:19:27 +03:00
# if defined ( TRACK_MONOOBJECTS )
xamarin_bridge _dump _monoobjects ( ) ;
# endif
2021-03-18 09:23:39 +03:00
}
2021-06-02 01:13:49 +03:00
static bool reference_tracking _end = false ;
// This callback will be called once before the GC starts calling xamarin_coreclr _reference _tracking _is _referenced _callback ,
// and once the GC is done . We keep track of which case we ' re in in the ' reference_tracking _end ' variable , and raise the
// corresponding GC event . It will only be called once for each GC , both the begin and the end on the same thread .
2021-05-31 09:10:34 +03:00
void
xamarin_coreclr _reference _tracking _begin _end _callback ( )
{
LOG_CORECLR ( stderr , "%s () reference_tracking_end: %i\n" , __func __ , reference_tracking _end ) ;
2021-06-02 01:13:49 +03:00
if ( reference_tracking _end ) {
xamarin_gc _event ( MONO_GC _EVENT _POST _START _WORLD ) ;
} else {
xamarin_gc _event ( MONO_GC _EVENT _PRE _STOP _WORLD ) ;
}
reference_tracking _end = ! reference_tracking _end ;
2021-05-31 09:10:34 +03:00
}
2021-06-02 01:13:49 +03:00
// This callback is called by the GC to check whether a given managed object
// can be collected or not . The single ' ptr ' argument is the native memory
// returned by the managed call to
// ObjectiveCMarshal . CreateReferenceTrackingHandle , and this memory can be
// accessed while the GC is running . In here we store the native Handle for
// the managed object , and any flags , both of which we need to know in this
// method to determine whether the corresponding managed object can be
// collected or not .
2021-05-31 09:10:34 +03:00
int
xamarin_coreclr _reference _tracking _is _referenced _callback ( void * ptr )
{
2021-06-02 01:13:49 +03:00
// This is a callback called by the GC , so there ' s not much we can do here safely .
// Most importantly we can ' t call managed code , nor access managed memory .
// But we can access the native memory given to us when the object was toggled
// ( and which is passed as the ' ptr ' argument ) , so let ' s get the data we need from there .
2021-05-31 09:10:34 +03:00
int rv = 0 ;
2021-06-02 01:13:49 +03:00
struct TrackedObjectInfo * info = ( struct TrackedObjectInfo * ) ptr ;
enum NSObjectFlags flags = info -> flags ;
2022-04-21 09:22:24 +03:00
bool isRegisteredToggleRef = ( flags & NSObjectFlagsRegisteredToggleRef ) = = NSObjectFlagsRegisteredToggleRef ;
2021-06-02 01:13:49 +03:00
id handle = info -> handle ;
2022-04-21 09:22:24 +03:00
MonoToggleRefStatus res = ( MonoToggleRefStatus ) 0 ;
if ( isRegisteredToggleRef ) {
res = xamarin_gc _toggleref _callback ( flags , handle , NULL , NULL ) ;
switch ( res ) {
case MONO_TOGGLE _REF _DROP :
// There ' s no equivalent to DROP in CoreCLR , so just treat it as weak .
case MONO_TOGGLE _REF _WEAK :
rv = 0 ;
break ;
case MONO_TOGGLE _REF _STRONG :
rv = 1 ;
break ;
default :
LOG_CORECLR ( stderr , "%s (%p -> handle: %p flags: %i): INVALID toggle ref value: %i\n" , __func __ , ptr , handle , flags , res ) ;
break ;
}
} else {
// If this isn ' t a toggle ref , it ' s effectively a weak gchandle
2021-06-02 01:13:49 +03:00
rv = 0 ;
}
2021-05-31 09:10:34 +03:00
2022-04-21 09:22:24 +03:00
LOG_CORECLR ( stderr , "%s (%p -> handle: %p flags: %i) => %i (res: %i) isRegisteredToggleRef: %i\n" , __func __ , ptr , handle , flags , rv , res , isRegisteredToggleRef ) ;
2021-05-31 09:10:34 +03:00
return rv ;
}
2021-06-02 01:13:49 +03:00
// This callback is called when an object is queued for finalization . The
// single ' ptr ' argument is the native memory returned by the managed call to
// ObjectiveCMarshal . CreateReferenceTrackingHandle , and this memory can be
// accessed while the GC is running ( which it is when this method is called ) .
// In here we set the NSObjectFlagsInFinalizerQueue flag , which managed code
// ( the NSObject . flags property ) will fetch .
2021-05-31 09:10:34 +03:00
void
xamarin_coreclr _reference _tracking _tracked _object _entered _finalization ( void * ptr )
{
2021-06-02 01:13:49 +03:00
struct TrackedObjectInfo * info = ( struct TrackedObjectInfo * ) ptr ;
info -> flags = ( enum NSObjectFlags ) ( info -> flags | NSObjectFlagsInFinalizerQueue ) ;
LOG_CORECLR ( stderr , "%s (%p) flags: %i\n" , __func __ , ptr , ( int ) info -> flags ) ;
2021-05-31 09:10:34 +03:00
}
void
xamarin_coreclr _unhandled _exception _handler ( void * context )
{
// ' context ' is the GCHandle returned by the managed Runtime . UnhandledExceptionPropagationHandler function .
GCHandle exception_gchandle = ( GCHandle ) context ;
LOG_CORECLR ( stderr , "%s (%p)\n" , __func __ , context ) ;
// xamarin_process _managed _exception _gchandle will free the GCHandle
xamarin_process _managed _exception _gchandle ( exception_gchandle ) ;
// The call to xamarin_process _managed _exception _gchandle should either abort or throw an Objective - C exception ,
// and in neither case should we end up here , so just assert .
xamarin_assertion _message ( "Failed to process unhandled managed exception." ) ;
}
2021-05-20 08:35:23 +03:00
void
xamarin_enable _new _refcount ( )
{
// Nothing to do here .
}
2021-07-16 17:15:17 +03:00
/ * *
* xamarin_bridge _decode _value :
*
* This implementation is a slightly modified copy ( to make it compile ) of mono_metadata _decode _value
* https : // github . com / dotnet / runtime / blob / 08 a7b2382799082eedb94d70fca6c66eb75f2872 / src / mono / mono / metadata / metadata . c # L1525
* /
guint32
xamarin_bridge _decode _value ( const char * _ptr , const char * * rptr )
{
const unsigned char * ptr = ( const unsigned char * ) _ptr ;
unsigned char b = * ptr ;
guint32 len ;
if ( ( b & 0 x80 ) = = 0 ) {
len = b ;
+ + ptr ;
} else if ( ( b & 0 x40 ) = = 0 ) {
len = ( guint32 ) ( ( b & 0 x3f ) < < 8 | ptr [ 1 ] ) ;
ptr + = 2 ;
} else {
len = ( guint32 ) ( ( ( b & 0 x1f ) < < 24 ) |
( ptr [ 1 ] < < 16 ) |
( ptr [ 2 ] < < 8 ) |
ptr [ 3 ] ) ;
ptr + = 4 ;
}
if ( rptr )
* rptr = ( char * ) ptr ;
return len ;
}
static char *
xamarin_read _config _string ( const char * * buf )
{
guint32 configLength = xamarin_bridge _decode _value ( * buf , buf ) ;
char * value = strndup ( * buf , configLength ) ;
* buf = * buf + configLength ;
return value ;
}
static void *
xamarin_mmap _runtime _config _file ( size_t * length )
{
if ( xamarin_runtime _configuration _name = = NULL ) {
LOG ( PRODUCT ": No runtime config file provided at build time.\n" ) ;
return NULL ;
}
char path [ 1024 ] ;
if ( ! xamarin_locate _app _resource ( xamarin_runtime _configuration _name , path , sizeof ( path ) ) ) {
LOG ( PRODUCT ": Could not locate the runtime config file '%s' in the app bundle.\n" , xamarin_runtime _configuration _name ) ;
return NULL ;
}
int fd = open ( path , O_RDONLY ) ;
if ( fd = = -1 ) {
LOG ( PRODUCT ": Could not open the runtime config file '%s' in the app bundle: %s\n" , path , strerror ( errno ) ) ;
return NULL ;
}
struct stat stat_buf = { 0 } ;
if ( fstat ( fd , & stat_buf ) = = -1 ) {
LOG ( PRODUCT ": Could not stat the runtime config file '%s' in the app bundle: %s\n" , path , strerror ( errno ) ) ;
close ( fd ) ;
return NULL ;
}
* length = ( size_t ) stat_buf . st_size ;
void * buffer = mmap ( NULL , * length , PROT_READ , MAP_PRIVATE , fd , 0 ) ;
close ( fd ) ;
return buffer ;
}
// Input : the property keys + values passed to xamarin_bridge _vm _initialize
// Output : newly allocated arrays of property keys + values that include those passed to xamarin_bridge _vm _initialize together with those in the runtimeconfig . bin file
// Caller must free the allocated arrays + their elements
void
xamarin_bridge _compute _properties ( int inputCount , const char * * inputKeys , const char * * inputValues , int * outputCount , const char * * * outputKeys , const char * * * outputValues )
{
size_t fd_len = 0 ;
const char * buf = ( const char * ) xamarin_mmap _runtime _config _file ( & fd_len ) ;
int runtimeConfigCount = 0 ;
if ( buf ! = NULL )
runtimeConfigCount = ( int ) xamarin_bridge _decode _value ( buf , & buf ) ;
// Allocate the output arrays
* outputCount = inputCount + runtimeConfigCount ;
* outputKeys = ( const char * * ) calloc ( ( size_t ) * outputCount , sizeof ( char * ) ) ;
* outputValues = ( const char * * ) calloc ( ( size_t ) * outputCount , sizeof ( char * ) ) ;
// Read the runtimeconfig properties
// https : // github . com / dotnet / runtime / blob / 57 bfe474518ab5b7cfe6bf7424a79ce3af9d6657 / docs / design / mono / mobile - runtimeconfig - json . md # the - encoded - runtimeconfig - format
for ( int i = 0 ; i < runtimeConfigCount ; i + + ) {
char * key = xamarin_read _config _string ( & buf ) ;
char * value = xamarin_read _config _string ( & buf ) ;
( * outputKeys ) [ i ] = key ;
( * outputValues ) [ i ] = value ;
}
// Copy the input properties
for ( int i = 0 ; i < inputCount ; i + + ) {
2022-05-25 09:31:26 +03:00
if ( inputKeys [ i ] ! = NULL && inputValues [ i ] ! = NULL ) {
( * outputKeys ) [ i + runtimeConfigCount ] = strdup ( inputKeys [ i ] ) ;
( * outputValues ) [ i + runtimeConfigCount ] = strdup ( inputValues [ i ] ) ;
} else {
NSLog ( @ PRODUCT ": No name/value specified for runtime property %s=%s" , inputKeys [ i ] , inputValues [ i ] ) ;
}
2021-07-16 17:15:17 +03:00
}
if ( buf ! = NULL )
munmap ( ( void * ) buf , fd_len ) ;
}
2023-06-21 21:49:49 +03:00
# if ! defined ( NATIVEAOT )
2021-03-22 10:04:56 +03:00
bool
xamarin_bridge _vm _initialize ( int propertyCount , const char * * propertyKeys , const char * * propertyValues )
{
int rv ;
2021-07-16 17:15:17 +03:00
int combinedPropertyCount = 0 ;
const char * * combinedPropertyKeys = NULL ;
const char * * combinedPropertyValues = NULL ;
xamarin_bridge _compute _properties ( propertyCount , propertyKeys , propertyValues , & combinedPropertyCount , & combinedPropertyKeys , & combinedPropertyValues ) ;
2021-03-22 10:04:56 +03:00
const char * executablePath = [ [ [ [ NSBundle mainBundle ] executableURL ] path ] UTF8String ] ;
rv = coreclr_initialize (
executablePath ,
xamarin_executable _name ,
2021-07-16 17:15:17 +03:00
combinedPropertyCount ,
combinedPropertyKeys ,
combinedPropertyValues ,
2021-03-22 10:04:56 +03:00
& coreclr_handle ,
& coreclr_domainId
) ;
2021-07-16 17:15:17 +03:00
for ( int i = 0 ; i < combinedPropertyCount ; i + + ) {
free ( ( void * ) combinedPropertyKeys [ i ] ) ;
free ( ( void * ) combinedPropertyValues [ i ] ) ;
}
free ( ( void * ) combinedPropertyKeys ) ;
free ( ( void * ) combinedPropertyValues ) ;
LOG_CORECLR ( stderr , "xamarin_vm_initialize (%i, %p, %p): rv: %i domainId: %i handle: %p\n" , combinedPropertyCount , combinedPropertyKeys , combinedPropertyValues , rv , coreclr_domainId , coreclr_handle ) ;
2021-03-22 10:04:56 +03:00
return rv = = 0 ;
}
2023-06-21 21:49:49 +03:00
# endif // ! defined ( NATIVEAOT )
2021-03-22 10:04:56 +03:00
2021-04-21 17:21:09 +03:00
void
xamarin_install _nsautoreleasepool _hooks ( )
{
2021-06-02 08:41:44 +03:00
// No need to do anything here for CoreCLR .
2021-04-21 17:21:09 +03:00
}
2021-05-13 08:12:17 +03:00
void
mono_runtime _set _pending _exception ( MonoException * exc , mono_bool overwrite )
{
LOG_CORECLR ( stderr , "%s (%p, %i)\n" , __func __ , exc , overwrite ) ;
xamarin_bridge _set _pending _exception ( exc ) ;
}
2021-03-24 11:26:31 +03:00
void
xamarin_handle _bridge _exception ( GCHandle gchandle , const char * method )
{
if ( gchandle = = INVALID_GCHANDLE )
return ;
if ( method = = NULL )
2021-05-21 16:53:10 +03:00
method = "<unknown method>" ;
2021-03-24 11:26:31 +03:00
2021-05-05 17:31:03 +03:00
fprintf ( stderr , "%s threw an exception: %p => %s\n" , method , gchandle , [ xamarin_print _all _exceptions ( gchandle ) UTF8String ] ) ;
xamarin_assertion _message ( "%s threw an exception: %p = %s" , method , gchandle , [ xamarin_print _all _exceptions ( gchandle ) UTF8String ] ) ;
2021-03-24 11:26:31 +03:00
}
2023-06-21 21:49:49 +03:00
# if ! defined ( NATIVEAOT )
typedef void ( * xamarin_runtime _initialize _decl ) ( struct InitializationOptions * options , GCHandle * exception_gchandle ) ;
2021-03-25 09:25:20 +03:00
void
xamarin_bridge _call _runtime _initialize ( struct InitializationOptions * options , GCHandle * exception_gchandle )
{
void * del = NULL ;
2023-06-21 21:49:49 +03:00
int rv = coreclr_create _delegate ( coreclr_handle , coreclr_domainId , PRODUCT ", Version=0.0.0.0" , "ObjCRuntime.Runtime" , "SafeInitialize" , & del ) ;
2021-03-25 09:25:20 +03:00
if ( rv ! = 0 )
xamarin_assertion _message ( "xamarin_bridge_call_runtime_initialize: failed to create delegate: %i\n" , rv ) ;
xamarin_runtime _initialize _decl runtime_initialize = ( xamarin_runtime _initialize _decl ) del ;
2023-06-21 21:49:49 +03:00
runtime_initialize ( options , exception_gchandle ) ;
2021-03-25 09:25:20 +03:00
}
2023-06-21 21:49:49 +03:00
# endif // ! defined ( NATIVEAOT )
2021-03-25 09:25:20 +03:00
void
xamarin_bridge _register _product _assembly ( GCHandle * exception_gchandle )
{
2021-03-22 14:53:52 +03:00
MonoAssembly * assembly ;
assembly = xamarin_open _and _register ( PRODUCT_DUAL _ASSEMBLY , exception_gchandle ) ;
xamarin_mono _object _release ( & assembly ) ;
2021-03-25 09:25:20 +03:00
}
2021-04-30 08:49:25 +03:00
MonoMethod *
xamarin_bridge _get _mono _method ( MonoReflectionMethod * method )
{
// MonoMethod and MonoReflectionMethod are identical in CoreCLR ( both are actually MonoObjects ) .
// However , we ' re returning a retained object , so we need to retain here .
xamarin_mono _object _retain ( method ) ;
LOG_CORECLR ( stderr , "%s (%p): rv: %p\n" , __func __ , method , method ) ;
return method ;
}
2021-05-14 08:29:48 +03:00
MonoType *
xamarin_get _nsnumber _type ( )
2021-03-25 09:25:20 +03:00
{
2021-05-14 08:29:48 +03:00
// xamarin_bridge _lookup _class returns a MonoClass * , and this method returns a MonoType * ,
// but they ' re interchangeable for CoreCLR ( they ' re all just MonoObject * s ) , so this is fine .
MonoClass * rv = xamarin_bridge _lookup _class ( XamarinLookupTypes_Foundation _NSNumber ) ;
LOG_CORECLR ( stderr , "%s () => %p\n" , __func __ , rv ) ;
return rv ;
2021-03-25 09:25:20 +03:00
}
2021-05-14 08:29:48 +03:00
MonoType *
xamarin_get _nsvalue _type ( )
2021-03-25 09:25:20 +03:00
{
2021-05-14 08:29:48 +03:00
// xamarin_bridge _lookup _class returns a MonoClass * , and this method returns a MonoType * ,
// but they ' re interchangeable for CoreCLR ( they ' re all just MonoObject * s ) , so this is fine .
MonoClass * rv = xamarin_bridge _lookup _class ( XamarinLookupTypes_Foundation _NSValue ) ;
LOG_CORECLR ( stderr , "%s () => %p\n" , __func __ , rv ) ;
return rv ;
2021-03-25 09:25:20 +03:00
}
2021-03-22 14:53:52 +03:00
void
xamarin_mono _object _retain ( MonoObject * mobj )
{
atomic_fetch _add ( & mobj -> reference_count , 1 ) ;
}
void
xamarin_mono _object _release ( MonoObject * * mobj_ref )
{
MonoObject * mobj = * mobj_ref ;
if ( mobj = = NULL )
return ;
int rc = atomic_fetch _sub ( & mobj -> reference_count , 1 ) - 1 ;
if ( rc = = 0 ) {
if ( mobj -> gchandle ! = INVALID_GCHANDLE ) {
xamarin_gchandle _free ( mobj -> gchandle ) ;
mobj -> gchandle = INVALID_GCHANDLE ;
}
2021-05-11 16:15:41 +03:00
xamarin_free ( mobj -> struct_value ) ; // allocated using Marshal . AllocHGlobal .
2021-03-22 14:53:52 +03:00
xamarin_free ( mobj ) ; // allocated using Marshal . AllocHGlobal .
2021-05-25 09:19:27 +03:00
# if defined ( TRACK_MONOOBJECTS )
if ( monoobject_dict ! = NULL ) {
pthread_mutex _lock ( & monoobject_lock ) ;
CFDictionaryRemoveValue ( monoobject_dict , mobj ) ;
pthread_mutex _unlock ( & monoobject_lock ) ;
}
atomic_fetch _add ( & monoobject_destroyed , 1 ) ;
# endif
2021-03-22 14:53:52 +03:00
}
* mobj_ref = NULL ;
}
2021-06-01 08:36:01 +03:00
void
xamarin_mono _object _release _at _process _exit ( MonoObject * mobj )
{
pthread_mutex _lock ( & monoobject_lock ) ;
release_at _exit = s_list _prepend ( release_at _exit , mobj ) ;
pthread_mutex _unlock ( & monoobject_lock ) ;
}
2021-03-22 14:53:52 +03:00
/ * Implementation of the Mono Embedding API * /
// returns a retained MonoAssembly *
MonoAssembly *
mono_assembly _open ( const char * filename , MonoImageOpenStatus * status )
{
MonoAssembly * rv = xamarin_find _assembly ( filename ) ;
LOG_CORECLR ( stderr , "mono_assembly_open (%s, %p) => MonoObject=%p GCHandle=%p\n" , filename , status , rv , rv -> gchandle ) ;
2022-06-03 11:41:43 +03:00
if ( status ! = NULL )
* status = rv = = NULL ? MONO_IMAGE _ERROR _ERRNO : MONO_IMAGE _OK ;
2021-03-22 14:53:52 +03:00
return rv ;
}
2021-05-10 15:42:47 +03:00
const char *
mono_class _get _namespace ( MonoClass * klass )
{
char * rv = xamarin_bridge _class _get _namespace ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %s\n" , __func __ , klass , rv ) ;
return rv ;
}
const char *
mono_class _get _name ( MonoClass * klass )
{
char * rv = xamarin_bridge _class _get _name ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %s\n" , __func __ , klass , rv ) ;
return rv ;
}
2021-05-13 23:04:09 +03:00
char *
mono_method _full _name ( MonoMethod * method , mono_bool signature )
{
char * rv = xamarin_bridge _get _method _full _name ( method ) ;
LOG_CORECLR ( stderr , "%s (%p, %i) => %s\n" , __func __ , method , signature , rv ) ;
return rv ;
}
2021-03-31 00:46:36 +03:00
MonoDomain *
mono_domain _get ( void )
{
// This is not needed for CoreCLR .
return NULL ;
}
2021-05-11 16:15:03 +03:00
MonoType *
mono_class _get _type ( MonoClass * klass )
{
// MonoClass and MonoType are identical in CoreCLR ( both are actually MonoObjects ) .
// However , we ' re returning a retained object , so we need to retain here .
MonoType * rv = klass ;
xamarin_mono _object _retain ( rv ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , klass , rv ) ;
return rv ;
}
2021-04-21 16:00:10 +03:00
// returns a retained MonoReflectionAssembly *
MonoReflectionAssembly *
mono_assembly _get _object ( MonoDomain * domain , MonoAssembly * assembly )
{
// MonoAssembly and MonoReflectionAssembly are identical in CoreCLR ( both are actually MonoObjects ) .
// However , we ' re returning a retained object , so we need to retain here .
xamarin_mono _object _retain ( assembly ) ;
LOG_CORECLR ( stderr , "mono_assembly_get_object (%p, %p): rv: %p\n" , domain , assembly , assembly ) ;
return assembly ;
}
2021-05-11 08:21:18 +03:00
MonoReflectionMethod *
mono_method _get _object ( MonoDomain * domain , MonoMethod * method , MonoClass * refclass )
{
// MonoMethod and MonoReflectionMethod are identical in CoreCLR ( both are actually MonoObjects ) .
// However , we ' re returning a retained object , so we need to retain here .
MonoReflectionMethod * rv = method ;
xamarin_mono _object _retain ( rv ) ;
LOG_CORECLR ( stderr , "%s (%p, %p, %p) => %p\n" , __func __ , domain , method , refclass , rv ) ;
return rv ;
}
2021-05-13 00:37:40 +03:00
MonoType *
mono_reflection _type _get _type ( MonoReflectionType * reftype )
{
// MonoType and MonoReflectionType are identical in CoreCLR ( both are actually MonoObjects ) .
// However , we ' re returning a retained object , so we need to retain here .
MonoType * rv = reftype ;
xamarin_mono _object _retain ( rv ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , reftype , rv ) ;
return rv ;
}
2023-06-21 21:49:49 +03:00
# if ! defined ( NATIVEAOT )
2021-04-22 08:46:56 +03:00
int
mono_jit _exec ( MonoDomain * domain , MonoAssembly * assembly , int argc , const char * * argv )
{
unsigned int exitCode = 0 ;
2021-07-14 18:42:49 +03:00
char * assemblyPath = xamarin_bridge _get _assembly _location ( assembly -> gchandle ) ;
2021-04-22 08:46:56 +03:00
2021-07-28 18:12:29 +03:00
if ( argc > 0 ) {
// The first argument is to the native executable , which we don ' t want to pass on to native code .
argc - - ;
argv = & argv [ 1 ] ;
}
2021-07-14 18:42:49 +03:00
LOG_CORECLR ( stderr , "mono_jit_exec (%p, %p, %i, %p) => EXECUTING %s\n" , domain , assembly , argc , argv , assemblyPath ) ;
2021-04-22 08:46:56 +03:00
for ( int i = 0 ; i < argc ; i + + ) {
LOG_CORECLR ( stderr , " Argument #%i: %s\n" , i + 1 , argv [ i ] ) ;
}
2021-07-14 18:42:49 +03:00
int rv = coreclr_execute _assembly ( coreclr_handle , coreclr_domainId , argc , argv , assemblyPath , & exitCode ) ;
2021-04-22 08:46:56 +03:00
2021-07-14 18:42:49 +03:00
LOG_CORECLR ( stderr , "mono_jit_exec (%p, %p, %i, %p) => EXECUTING %s rv: %i exitCode: %i\n" , domain , assembly , argc , argv , assemblyPath , rv , exitCode ) ;
2021-04-22 08:46:56 +03:00
2021-07-14 18:42:49 +03:00
xamarin_free ( assemblyPath ) ;
2021-04-22 08:46:56 +03:00
if ( rv ! = 0 )
xamarin_assertion _message ( "mono_jit_exec failed: %i\n" , rv ) ;
return ( int ) exitCode ;
}
2023-06-21 21:49:49 +03:00
# endif // ! defined ( NATIVEAOT )
2021-04-22 08:46:56 +03:00
2021-05-11 23:16:41 +03:00
MonoGHashTable *
mono_g _hash _table _new _type ( GHashFunc hash_func , GEqualFunc key_equal _func , MonoGHashGCType type )
{
MonoGHashTable * rv = xamarin_bridge _mono _hash _table _create ( hash_func , key_equal _func , type ) ;
LOG_CORECLR ( stderr , "%s (%p, %p, %u) => %p\n" , __func __ , hash_func , key_equal _func , type , rv ) ;
return rv ;
}
gpointer
mono_g _hash _table _lookup ( MonoGHashTable * hash , gconstpointer key )
{
MonoObject * rv = xamarin_bridge _mono _hash _table _lookup ( hash , key ) ;
LOG_CORECLR ( stderr , "%s (%p, %p) => %p\n" , __func __ , hash , key , rv ) ;
return rv ;
}
void
mono_g _hash _table _insert ( MonoGHashTable * hash , gpointer k , gpointer v )
{
MonoObject * obj = ( MonoObject * ) v ;
LOG_CORECLR ( stderr , "%s (%p, %p, %p)\n" , __func __ , hash , k , v ) ;
xamarin_bridge _mono _hash _table _insert ( hash , k , obj ) ;
}
2021-04-30 08:53:30 +03:00
MonoClass *
mono_method _get _class ( MonoMethod * method )
{
MonoClass * rv = xamarin_bridge _get _method _declaring _type ( method ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , method , rv ) ;
return rv ;
}
2021-05-04 15:31:20 +03:00
MonoClass *
mono_object _get _class ( MonoObject * obj )
{
MonoClass * rv = xamarin_bridge _object _get _type ( obj ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , obj , rv ) ;
return rv ;
}
2021-05-04 21:20:46 +03:00
MonoObject *
mono_object _isinst ( MonoObject * obj , MonoClass * klass )
{
bool rv = xamarin_bridge _isinstance ( obj , klass ) ;
LOG_CORECLR ( stderr , "%s (%p, %p) => %i\n" , __func __ , obj , klass , rv ) ;
return rv ? obj : NULL ;
}
2021-05-13 21:38:21 +03:00
MonoObject *
mono_value _box ( MonoDomain * domain , MonoClass * klass , void * val )
{
MonoObject * rv = xamarin_bridge _box ( klass , val ) ;
LOG_CORECLR ( stderr , "%s (%p, %p, %p) => %p\n" , __func __ , domain , klass , val , rv ) ;
return rv ;
}
2021-05-11 16:15:41 +03:00
void *
mono_object _unbox ( MonoObject * obj )
{
void * rv = obj -> struct_value ;
if ( rv = = NULL )
xamarin_assertion _message ( "%s (%p) => no struct value?\n" , __func __ ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , obj , rv ) ;
return rv ;
}
2021-05-06 17:19:59 +03:00
// Return value : NULL , or a retained MonoObject * that must be freed with xamarin_mono _object _release .
// Returns NULL in case of exception .
2021-05-06 08:25:43 +03:00
MonoObject *
mono_runtime _invoke ( MonoMethod * method , void * obj , void * * params , MonoObject * * exc )
{
MonoObject * rv = NULL ;
GCHandle exception_gchandle = INVALID_GCHANDLE ;
LOG_CORECLR ( stderr , "%s (%p, %p, %p, %p)\n" , __func __ , method , obj , params , exc ) ;
rv = xamarin_bridge _runtime _invoke _method ( method , ( MonoObject * ) obj , params , & exception_gchandle ) ;
if ( exc = = NULL ) {
xamarin_handle _bridge _exception ( exception_gchandle , __func __ ) ;
} else {
* exc = xamarin_gchandle _unwrap ( exception_gchandle ) ;
}
return rv ;
}
2021-05-14 08:27:42 +03:00
MonoException *
xamarin_create _system _exception ( const char * message )
{
MonoException * rv = xamarin_bridge _create _exception ( XamarinExceptionTypes_System _Exception , message ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , message , rv ) ;
return rv ;
}
MonoException *
xamarin_create _system _invalid _cast _exception ( const char * message )
{
MonoException * rv = xamarin_bridge _create _exception ( XamarinExceptionTypes_System _InvalidCastException , message ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , message , rv ) ;
return rv ;
}
MonoException *
xamarin_create _system _entry _point _not _found _exception ( const char * entrypoint )
{
MonoException * rv = xamarin_bridge _create _exception ( XamarinExceptionTypes_System _EntryPointNotFoundException , entrypoint ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , entrypoint , rv ) ;
return rv ;
}
2021-05-20 08:33:16 +03:00
MonoException *
mono_get _exception _out _of _memory ( )
{
MonoException * rv = xamarin_bridge _create _exception ( XamarinExceptionTypes_System _OutOfMemoryException , NULL ) ;
2022-05-10 10:26:20 +03:00
LOG_CORECLR ( stderr , "%s () => %p\n" , __func __ , rv ) ;
2021-05-20 08:33:16 +03:00
return rv ;
}
2021-05-06 17:19:59 +03:00
MonoMethodSignature *
mono_method _signature ( MonoMethod * method )
{
MonoMethodSignature * rv = xamarin_bridge _method _get _signature ( method ) ;
2021-05-21 08:54:42 +03:00
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , method , rv ) ;
2021-05-06 17:19:59 +03:00
return rv ;
}
MonoType *
mono_signature _get _params ( MonoMethodSignature * sig , void * * iter )
{
int * p = ( int * ) iter ;
if ( * p >= sig -> parameter_count ) {
LOG_CORECLR ( stderr , "%s (%p, %p => %i) => DONE\n" , __func __ , sig , iter , * p ) ;
return NULL ;
}
MonoObject * rv = sig -> parameters [ * p ] ;
xamarin_mono _object _retain ( rv ) ;
LOG_CORECLR ( stderr , "%s (%p, %p => %i) => %p NEXT\n" , __func __ , sig , iter , * p , rv -> gchandle ) ;
* p = * p + 1 ;
return rv ;
}
MonoType *
mono_signature _get _return _type ( MonoMethodSignature * sig )
{
MonoType * rv = sig -> return_type ;
xamarin_mono _object _retain ( rv ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , sig , rv ) ;
return rv ;
}
2021-05-10 16:38:13 +03:00
MonoReflectionType *
mono_type _get _object ( MonoDomain * domain , MonoType * type )
{
MonoReflectionType * rv = type ;
xamarin_mono _object _retain ( rv ) ;
LOG_CORECLR ( stderr , "%s (%p, %p) => %p\n" , __func __ , domain , type , rv ) ;
return rv ;
}
2021-05-06 17:19:59 +03:00
void
xamarin_bridge _free _mono _signature ( MonoMethodSignature * * psig )
{
MonoMethodSignature * sig = * psig ;
2021-05-14 08:28:53 +03:00
if ( sig = = NULL )
return ;
2021-06-01 14:09:43 +03:00
xamarin_mono _object _release ( & sig -> method ) ;
2021-05-06 17:19:59 +03:00
for ( int i = 0 ; i < sig -> parameter_count ; i + + ) {
xamarin_mono _object _release ( & sig -> parameters [ i ] ) ;
}
xamarin_mono _object _release ( & sig -> return_type ) ;
mono_free ( sig ) ;
* psig = NULL ;
}
2021-05-10 08:25:45 +03:00
void
mono_free ( void * ptr )
{
free ( ptr ) ;
}
mono_bool
mono_thread _detach _if _exiting ( )
{
// Nothing to do here for CoreCLR .
return true ;
}
2021-05-07 16:47:03 +03:00
MonoClass *
mono_class _from _mono _type ( MonoType * type )
{
MonoClass * rv = xamarin_bridge _type _to _class ( type ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , type , rv ) ;
return rv ;
}
2021-05-12 16:22:11 +03:00
MonoClass *
mono_get _string _class ( )
{
2021-05-14 08:29:48 +03:00
MonoClass * rv = xamarin_bridge _lookup _class ( XamarinLookupTypes_System _String ) ;
2021-05-12 16:22:11 +03:00
LOG_CORECLR ( stderr , "%s () => %p.\n" , __func __ , rv ) ;
return rv ;
}
2021-05-14 16:19:23 +03:00
mono_bool
mono_class _is _enum ( MonoClass * klass )
{
bool rv = xamarin_bridge _is _enum ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %i\n" , __func __ , klass , rv ) ;
return rv ;
}
MonoType *
mono_class _enum _basetype ( MonoClass * klass )
{
MonoType * rv = xamarin_bridge _get _enum _basetype ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , klass , rv ) ;
return rv ;
}
2021-05-10 16:10:03 +03:00
mono_bool
mono_type _is _byref ( MonoType * type )
{
bool rv = xamarin_bridge _is _byref ( type ) ;
LOG_CORECLR ( stderr , "%s (%p) => %i\n" , __func __ , type , rv ) ;
return rv ;
}
2021-05-07 23:21:19 +03:00
mono_bool
mono_class _is _delegate ( MonoClass * klass )
{
bool rv = xamarin_bridge _is _delegate ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %i\n" , __func __ , klass , rv ) ;
return rv ;
}
2021-05-10 16:10:03 +03:00
mono_bool
mono_class _is _valuetype ( MonoClass * klass )
{
bool rv = xamarin_bridge _is _valuetype ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %i\n" , __func __ , klass , rv ) ;
return rv ;
}
2021-05-14 16:19:34 +03:00
int32_t
mono_class _value _size ( MonoClass * klass , uint32_t * align )
{
int32_t rv = xamarin_bridge _sizeof ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p, %p) => %i\n" , __func __ , klass , align , rv ) ;
return rv ;
}
2021-05-13 23:03:22 +03:00
gboolean
mono_class _is _nullable ( MonoClass * klass )
{
bool rv = xamarin_bridge _is _nullable ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %i\n" , __func __ , klass , rv ) ;
return rv ;
}
2021-05-12 08:31:26 +03:00
MonoClass *
mono_class _get _element _class ( MonoClass * klass )
{
MonoClass * rv = xamarin_bridge _get _element _class ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , klass , rv ) ;
2021-05-13 21:39:07 +03:00
return rv ;
}
MonoClass *
mono_class _get _nullable _param ( MonoClass * klass )
{
MonoClass * rv = xamarin_bridge _get _nullable _element _type ( klass ) ;
LOG_CORECLR ( stderr , "%s (%p) => %p\n" , __func __ , klass , rv ) ;
2021-05-12 08:31:26 +03:00
return rv ;
}
2021-05-11 00:12:52 +03:00
bool
xamarin_is _class _nsobject ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_Foundation _NSObject ) ;
}
bool
xamarin_is _class _inativeobject ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_ObjCRuntime _INativeObject ) ;
}
2021-11-17 12:30:52 +03:00
bool
xamarin_is _class _nativehandle ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_ObjCRuntime _NativeHandle ) ;
}
2021-05-11 00:12:52 +03:00
bool
xamarin_is _class _array ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_System _Array ) ;
}
bool
xamarin_is _class _nsnumber ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_Foundation _NSNumber ) ;
}
bool
xamarin_is _class _nsvalue ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_Foundation _NSValue ) ;
}
bool
xamarin_is _class _nsstring ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_Foundation _NSString ) ;
}
bool
xamarin_is _class _intptr ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_System _IntPtr ) ;
}
bool
xamarin_is _class _string ( MonoClass * cls )
{
return xamarin_bridge _is _class _of _type ( cls , XamarinLookupTypes_System _String ) ;
}
2021-05-10 16:10:03 +03:00
2021-05-12 16:21:56 +03:00
MonoArray *
mono_array _new ( MonoDomain * domain , MonoClass * eclass , uintptr_t n )
{
MonoArray * rv = xamarin_bridge _create _array ( eclass , n ) ;
LOG_CORECLR ( stderr , "%s (%p, %p, %" PRIdPTR ") => %p\n" , __func __ , domain , eclass , n , rv ) ;
return rv ;
}
uintptr_t
mono_array _length ( MonoArray * array )
{
uintptr_t rv = ( uintptr_t ) xamarin_bridge _get _array _length ( array ) ;
LOG_CORECLR ( stderr , "%s (%p) => %llu\n" , __func __ , array , ( uint64_t ) rv ) ;
return rv ;
}
2021-05-11 16:16:01 +03:00
char *
mono_string _to _utf8 ( MonoString * string_obj )
{
char * rv = xamarin_bridge _string _to _utf8 ( string_obj ) ;
LOG_CORECLR ( stderr , "%s (%p) => %s\n" , __func __ , string_obj , rv ) ;
return rv ;
}
MonoString *
mono_string _new ( MonoDomain * domain , const char * text )
{
MonoString * rv = xamarin_bridge _new _string ( text ) ;
LOG_CORECLR ( stderr , "%s (%p, %s) => %p\n" , __func __ , domain , text , rv ) ;
return rv ;
}
2021-03-18 09:23:39 +03:00
# endif // CORECLR_RUNTIME