Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
50c65cf
[runtime] Extract logic in xamarin_unhandled_exception_handler to col…
rolfbjarne May 11, 2016
ac705ce
[runtime] Make the existing trampolines exception-aware.
rolfbjarne May 11, 2016
b8abf3d
Add runtime variable to specify if the Coop GC should be used, and a …
rolfbjarne May 11, 2016
9b4f753
Add runtime variable to specify the exception marshalling modes, and …
rolfbjarne May 11, 2016
3903e01
[mmp/mtouch] Add a Driver.WriteIfDifferent overload that takes a byte…
rolfbjarne May 11, 2016
86c73f8
Refactor static registrar to produce both a header and a source file.
rolfbjarne May 11, 2016
1f1f699
Implement support for exception marshalling.
rolfbjarne May 11, 2016
1ef9dfb
[runtime] Make sure the movaps instruction only accesses 16-byte alig…
rolfbjarne May 12, 2016
515ed01
Add libmonotouch.csproj / xamios.csproj to Xamarin.iOS.sln.
rolfbjarne May 12, 2016
3ac40ab
[runtime] Improve a few assertion messages to include more information.
rolfbjarne May 12, 2016
79c6823
[runtime] Don't use NSMethodSignature to compute frame size, it can't…
rolfbjarne May 12, 2016
e8e8d6e
[runtime] Fix lookup of the inner exception when printing exception m…
rolfbjarne May 12, 2016
e51c48c
[runtime] Don't store xmm registers where we store other registers.
rolfbjarne May 12, 2016
feb12f6
[runtime] mono_set_pending_exception is a private function in mono, s…
rolfbjarne May 12, 2016
f478657
[runtime] Only insert dllmap for exception marshalling when the ObjC …
rolfbjarne May 12, 2016
5358242
[runtime] Use the right condition when to reference libxammac.dylib v…
rolfbjarne May 12, 2016
7c1b81e
[runtime] Make sure the stack is correctly aligned to 16 bytes.
rolfbjarne May 12, 2016
f631069
[mmp] Only 64-bit apps have the dynamic objc_msgSend wrappers.
rolfbjarne May 12, 2016
62cbe7e
[mtouch] Fix logic to detect if simlauncher can be used.
rolfbjarne May 13, 2016
2f2ac89
[mtouch] Remove misleading comment.
rolfbjarne May 13, 2016
f7a5b7f
[runtime] Add docs about exception marshaling.
rolfbjarne May 13, 2016
cffc2e9
Rewrite user-visible messages to use 'cooperative mode' instead of 'c…
rolfbjarne May 17, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions Xamarin.iOS.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{2BFA13F8
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "introspection-ios", "tests\introspection\iOS\introspection-ios.csproj", "{208744BD-504E-47D7-9A98-1CF02454A6DA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libmonotouch", "runtime\libmonotouch.csproj", "{8A5B637C-E4FF-4145-B887-9347020100F4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xamios", "src\xamios.csproj", "{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -168,6 +172,74 @@ Global
{208744BD-504E-47D7-9A98-1CF02454A6DA}.Release|iPhone.Build.0 = Release|iPhone
{208744BD-504E-47D7-9A98-1CF02454A6DA}.DebugStaticRegistrar|iPhone.ActiveCfg = DebugStaticRegistrar|iPhone
{208744BD-504E-47D7-9A98-1CF02454A6DA}.DebugStaticRegistrar|iPhone.Build.0 = DebugStaticRegistrar|iPhone
{8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Release|Any CPU.Build.0 = Release|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Debug|iPhone.Build.0 = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Release|iPhone.ActiveCfg = Release|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.Release|iPhone.Build.0 = Release|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.DebugStaticRegistrar|iPhone.ActiveCfg = Debug|Any CPU
{8A5B637C-E4FF-4145-B887-9347020100F4}.DebugStaticRegistrar|iPhone.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|Any CPU.Build.0 = Release|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Debug|iPhone.Build.0 = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhone.ActiveCfg = Release|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.Release|iPhone.Build.0 = Release|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.DebugStaticRegistrar|iPhone.ActiveCfg = Debug|Any CPU
{E1F334C3-8F77-46C9-A28B-A8E9BAEA9FE5}.DebugStaticRegistrar|iPhone.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{208744BD-504E-47D7-9A98-1CF02454A6DA} = {2BFA13F8-B568-48BF-9A70-9D43F718C523}
Expand Down
127 changes: 127 additions & 0 deletions runtime/EXCEPTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
History
====================

Historically we've attempted to convert Objective-C exceptions to managed exceptions
by adding a handler to be notified of uncaught Objective-C exceptions [1], but that one
major problem: it did not handle *caught* Objective-C exceptions, where the exception
handler would just abort.

This is common in iOS apps, where the main runloop adds an Objective-C @try/@catch
handler that just aborts, preventing us from being notified of the Objectice-C exception.

This approach also has another problem: the Objective-C exception handling mechanism
could unwind through managed code, which would result in all kinds of inexplicable
behavior (if there was an Objective-C exception handler that _didn't_ abort the app):

try {
doSomethingThatCausesAnObjectiveCException ();
} finally {
Console.WriteLine ("Done!");
}

If there happened to be an Objective-C exception handler in a stack frame further
up, the Console.WriteLine would never be executed.

Another frequent problem would occur in an IDE debugger if it tried to evaluate
every property for an object. If there were properties not supported on the
executing platform, it would throw an Objective-C exception (selector not found)
that would terminate the app.

The reverse problem also existed: throwing a managed exception that the native-to-managed
boundary didn't catch, would make the mono runtime unwind through native frames,
causing a similar set of inexplicable behavior:

[obj selectorThatManagedCodeHasOverriddenAndThrowAManagedException];
NSLog (@"done!");

The NSLog statement would never be executed.

[1] By using [NSSetUncaughtExceptionHandler](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/#//apple_ref/c/func/NSSetUncaughtExceptionHandler).

Exception marshaling
====================

There are two parts to exception marshaling: Objective-C exceptions
and managed exceptions.

In both cases we offer a managed event the app can subscribe to to
be notified, and then the app can choose what to do:

1. Convert the managed/Objective-C exception to its counterpart
(i.e. managed exceptions are converted to an Objective-C exception,
and Objective-C exceptions are converted to a managed exception).

2. Abort.

3. Rethrow the original exception (this is not available when
using the Coop GC, which is the only option on watchOS).

Managed exception marshaling
----------------------------

This is the simplest case, we just make sure to catch any managed
exceptions that reaches native code. There are a few sources:

1. When we call mono_runtime_invoke in our trampolines.

In this case mono_runtime_invoke will catch any exceptions
and return them to us (without unwinding anything else).

2. When managed code gives a delegate to native code, and
native code calls that delegate.

This is still a TODO, we need to use this new API to be
notified when the mono runtime detects this case:
https://github.com/mono/mono/pull/2948

Objective-C exception marshaling
--------------------------------

This is more complicated, because there must be an Objective-C
exception handler on the managed-to-native boundary frame,
catching the Objective-C exception.

We have two approaches for this:

1. Custom wrappers of the objc_msgSend functions with an
Objective-C exception handler. These have to be written
in assembly code, since it's not possible to do it in C.
At runtime we inject a dllmap into the process, which
redirects any P/invoke to the objc_msgSend functions to
these custom wrappers.

Since we can't write assembly code for bitcode targets
(watchOS), another approach is still required though.

This is the used for iOS/tvOS/watchOS simulator builds
(both 32-bit and 64-bit) and Mac/64 bits. It does not
work on Mac/32 bits because that platform does not use
0-cost exceptions like the other platforms (it uses
setjmp/longjmp instead, and would require a very
different implementation in assembly code).

The assembly code for these wrappers is in the
trampolines-[arch]-objc_msgSend* files.

The documentation about 0-cost exceptions is scarce,
but here are a few documents which were helpful:

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html
https://sourceware.org/binutils/docs/as/CFI-directives.html
http://mentorembedded.github.io/cxx-abi/abi-eh.html
http://llvm.org/docs/ExceptionHandling.html
http://www.opensource.apple.com/source/llvmCore/llvmCore-3425.0.33/docs/ExceptionHandling.rst
http://stackoverflow.com/a/7535848
http://www.darlinghq.org/for-developers/exception-handling-on-os-x

The wrappers themselves were first created by writing
something similar in C, and then telling clang to
dump the corresponding assembly code (by passing
`--save-temps -fverbose-asm` to clang).

2. At build time generate custom wrappers of every P/Invoke
to the objc_msgSend functions, and modify the P/Invoke to
call these generated wrappers.

This is used for iOS/tvOS/watchOS device builds, and
Mac/32 bits.
4 changes: 2 additions & 2 deletions runtime/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ SHIPPED_HEADERS += \
xamarin/runtime.h \

SHARED_SOURCES += mono-runtime.m bindings.m bindings-generated.m shared.m runtime.m trampolines.m trampolines-invoke.m xamarin-support.m nsstring-localization.m trampolines-varargs.m
SHARED_I386_SOURCES += trampolines-i386.m trampolines-i386-asm.s
SHARED_X86_64_SOURCES += trampolines-x86_64.m trampolines-x86_64-asm.s
SHARED_I386_SOURCES += trampolines-i386.m trampolines-i386-asm.s trampolines-i386-objc_msgSend.s trampolines-i386-objc_msgSendSuper.s trampolines-i386-objc_msgSend_stret.s trampolines-i386-objc_msgSendSuper_stret.s
SHARED_X86_64_SOURCES += trampolines-x86_64.m trampolines-x86_64-asm.s trampolines-x86_64-objc_msgSend.s trampolines-x86_64-objc_msgSendSuper.s trampolines-x86_64-objc_msgSend_stret.s trampolines-x86_64-objc_msgSendSuper_stret.s
SHARED_HEADERS += shared.h product.h delegates.h runtime-internal.h $(SHARED_INC) $(SHIPPED_HEADERS) trampolines-internal.h slinked-list.h

SHARED_FILES = $(SHARED_SOURCES) $(SHARED_HEADERS) $(SHARED_I386_SOURCES) $(SHARED_X86_64_SOURCES)
Expand Down
16 changes: 16 additions & 0 deletions runtime/delegates.t4
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@
"NSException *", "IntPtr", "exc"
) { WrappedManagedFunction = "ThrowNSException" },

new XDelegate ("int", "int", "xamarin_create_ns_exception",
"NSException *", "IntPtr", "exc"
) { WrappedManagedFunction = "CreateNSException" },

new XDelegate ("NSException *", "IntPtr", "xamarin_unwrap_ns_exception",
"int", "int", "exc_handle"
) { WrappedManagedFunction = "UnwrapNSException" },

new XDelegate ("MonoObject *", "IntPtr", "xamarin_get_block_wrapper_creator",
"MonoObject *", "IntPtr", "method",
"int", "int", "parameter"
Expand Down Expand Up @@ -147,6 +155,14 @@
new XDelegate ("char *", "IntPtr", "xamarin_lookup_managed_type_name",
"Class", "IntPtr", "klass"
) { WrappedManagedFunction = "LookupManagedTypeName" },

new XDelegate ("MarshalManagedExceptionMode", "MarshalManagedExceptionMode", "xamarin_on_marshal_managed_exception",
"int", "int", "exception"
) { WrappedManagedFunction = "OnMarshalManagedException" },

new XDelegate ("MarshalObjectiveCExceptionMode", "MarshalObjectiveCExceptionMode", "xamarin_on_marshal_objectivec_exception",
"id", "IntPtr", "exception"
) { WrappedManagedFunction = "OnMarshalObjectiveCException" },
};
delegates.CalculateLengths ();
#><#+
Expand Down
16 changes: 16 additions & 0 deletions runtime/exports.t4
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@

#endregion

#region metadata/object-internals.h

new Export (true, "void", "mono_set_pending_exception",
"MonoException *", "exc"
),

#endregion

#region metadata/assembly.h

new Export ("void", "mono_set_assemblies_path",
Expand Down Expand Up @@ -288,6 +296,14 @@
"MonoMethod *", "method"
),

new Export ("void", "mono_dllmap_insert",
"MonoImage *", "assembly",
"const char *", "dll",
"const char *", "func",
"const char *", "tdll",
"const char *", "tfunc"
),

#endregion

#region metadata/appdomain.h
Expand Down
14 changes: 14 additions & 0 deletions runtime/libmonotouch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,19 @@
<None Include="trampolines-i386.m" />
<None Include="trampolines-varargs.h" />
<None Include="trampolines-varargs.m" />
<None Include="trampolines-x86_64-objc_msgSendSuper.s" />
<None Include="trampolines-x86_64-objc_msgSend.s" />
<None Include="trampolines-x86_64-objc_msgSend-post.inc" />
<None Include="trampolines-x86_64-objc_msgSend-copyframe.inc" />
<None Include="trampolines-x86_64-objc_msgSend-pre.inc" />
<None Include="trampolines-x86_64-objc_msgSend_stret.s" />
<None Include="trampolines-x86_64-objc_msgSendSuper_stret.s" />
<None Include="trampolines-i386-objc_msgSend.s" />
<None Include="trampolines-i386-objc_msgSendSuper.s" />
<None Include="trampolines-i386-objc_msgSend_stret.s" />
<None Include="trampolines-i386-objc_msgSendSuper_stret.s" />
<None Include="trampolines-i386-objc_msgSend-copyframe.inc" />
<None Include="trampolines-i386-objc_msgSend-post.inc" />
<None Include="trampolines-i386-objc_msgSend-pre.inc" />
</ItemGroup>
</Project>
15 changes: 15 additions & 0 deletions runtime/runtime-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,19 @@

void *xamarin_marshal_return_value (MonoType *mtype, const char *type, MonoObject *retval, bool retain, MonoMethod *method);

/*
* XamarinGCHandle
*
* This is an ObjC type that ties the lifetime of a GCHandle to the lifetime of itself.
* It stores a GCHandle, and frees the GCHandle in dealloc.
*/
@interface XamarinGCHandle : NSObject {
@public
int handle;
}
+(XamarinGCHandle *) createWithHandle: (int) handle;
-(void) dealloc;
-(int) getHandle;
@end

#endif /* __RUNTIME_INTERNAL_H__ */
Loading