Bridges the worlds of .NET with the native APIs of macOS, iOS, tvOS, and watchOS.
Перейти к файлу
Sebastien Pouliot 2d7edf555f
[objcruntime] Add helper to check for disposed instances (#8679)
We're handling `ObjectDisposedException` a bit inconsistently in our
bindings.

Some, but not all, manual bindings have checks (not all of them are fully
consistent) but there's none for generated bindings, which can lead to
errors wrt nullability.

**Example**

```
[Test]
public void IncompleteNullabilityCheck ()
{
	NSString s = new NSString ("bonjour");
	s.Dispose ();
	ManagedLayer (s);
}

void ManagedLayer (NSString s)
{
	// this is similar to the generated binding code
	if (s == null)
		throw new ArgumentNullException ("s");
	NativeCode (s.Handle);
}

void NativeCode (IntPtr p)
{
	// let's assume this is native and dereference the pointer
	if (p == IntPtr.Zero)
		Assert.Fail ("boo");
}
```

This shows that we can, _if disposed_, provide `nil` to a native API for
which we know `nil` is not a valid argument. That can crash a process in
a situation that was possible to detect and throw a (catchable) managed
exception.

Adding dispose checks everywhere could be costly (in size) unless we
share that code with the null check (and a few other optimizations could
be applied too). Sharing the code would also ensure more consistency
across all bindings.

**Impact**

Here's the IL for an existing `CGColor` constructor that *already*
does the dispose check.

```
.method public hidebysig specialname rtspecialname
	instance void .ctor (
		class CoreGraphics.CGColorSpace colorspace,
		valuetype System.nfloat[] components
	) cil managed
{
	// Method begins at RVA 0x20c834
	// Code size 82 (0x52)
	.maxstack 3

	IL_0000: ldarg.0
	IL_0001: call instance void [mscorlib]System.Object::.ctor()
	IL_0006: ldarg.2
	IL_0007: brtrue.s IL_0014

	IL_0009: ldstr "components"
	IL_000e: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_0013: throw

	IL_0014: ldarg.1
	IL_0015: brtrue.s IL_0022

	IL_0017: ldstr "colorspace"
	IL_001c: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_0021: throw

	IL_0022: ldarg.1
	IL_0023: ldfld native int CoreGraphics.CGColorSpace::handle
	IL_0028: ldsfld native int [mscorlib]System.IntPtr::Zero
	IL_002d: call bool [mscorlib]System.IntPtr::op_Equality(native int, native int)
	IL_0032: brfalse.s IL_003f

	IL_0034: ldstr "colorspace"
	IL_0039: newobj instance void [mscorlib]System.ObjectDisposedException::.ctor(string)
	IL_003e: throw

	IL_003f: ldarg.0
	IL_0040: ldarg.1
	IL_0041: ldfld native int CoreGraphics.CGColorSpace::handle
	IL_0046: ldarg.2
	IL_0047: call native int CoreGraphics.CGColor::CGColorCreate(native int, valuetype System.nfloat[])
	IL_004c: stfld native int CoreGraphics.CGColor::handle
	IL_0051: ret
} // end of method CGColor::.ctor

Here's the IL code (as committed) using a helper extension method.

```
.method public hidebysig specialname rtspecialname
	instance void .ctor (
		class CoreGraphics.CGColorSpace colorspace,
		valuetype System.nfloat[] components
	) cil managed
{
	// Method begins at RVA 0x210558
	// Code size 46 (0x2e)
	.maxstack 3
	.locals init (
		[0] native int handleof_colorspace
	)

	IL_0000: ldarg.0
	IL_0001: call instance void [mscorlib]System.Object::.ctor()
	IL_0006: ldarg.2
	IL_0007: brtrue.s IL_0014

	IL_0009: ldstr "components"
	IL_000e: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_0013: throw

	IL_0014: ldarg.1
	IL_0015: ldstr "colorspace"
	IL_001a: call native int ObjCRuntime.NativeObjectHelper::GetNonNullHandle(class ObjCRuntime.INativeObject, string)
	IL_001f: stloc.0
	IL_0020: ldarg.0
	IL_0021: ldloc.0
	IL_0022: ldarg.2
	IL_0023: call native int CoreGraphics.CGColor::CGColorCreate(native int, valuetype System.nfloat[])
	IL_0028: stfld native int CoreGraphics.CGColor::handle
	IL_002d: ret
} // end of method CGColor::.ctor
```

So existing checks becomes a lot smaller. Here's another example where
a dispose check is **missing** (on `pattern`). Note that the check for
`colorspace` is not updated so we can see the impact of adding missing
dispose checks in existing code (manual or generated).

```
.method public hidebysig specialname rtspecialname
	instance void .ctor (
		class CoreGraphics.CGColorSpace colorspace,
		class CoreGraphics.CGPattern pattern,
		valuetype System.nfloat[] components
	) cil managed
{
	// Method begins at RVA 0x210660
	// Code size 126 (0x7e)
	.maxstack 4

	IL_0000: ldarg.0
	IL_0001: call instance void [mscorlib]System.Object::.ctor()
	IL_0006: ldarg.1
	IL_0007: brtrue.s IL_0014

	IL_0009: ldstr "colorspace"
	IL_000e: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_0013: throw

	IL_0014: ldarg.1
	IL_0015: ldfld native int CoreGraphics.CGColorSpace::handle
	IL_001a: ldsfld native int [mscorlib]System.IntPtr::Zero
	IL_001f: call bool [mscorlib]System.IntPtr::op_Equality(native int, native int)
	IL_0024: brfalse.s IL_0031

	IL_0026: ldstr "colorspace"
	IL_002b: newobj instance void [mscorlib]System.ObjectDisposedException::.ctor(string)
	IL_0030: throw

	IL_0031: ldarg.2
	IL_0032: brtrue.s IL_003f

	IL_0034: ldstr "pattern"
	IL_0039: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_003e: throw

	IL_003f: ldarg.3
	IL_0040: brtrue.s IL_004d

	IL_0042: ldstr "components"
	IL_0047: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_004c: throw

	IL_004d: ldarg.0
	IL_004e: ldarg.1
	IL_004f: ldfld native int CoreGraphics.CGColorSpace::handle
	IL_0054: ldarg.2
	IL_0055: callvirt instance native int CoreFoundation.NativeObject::get_Handle()
	IL_005a: ldarg.3
	IL_005b: call native int CoreGraphics.CGColor::CGColorCreateWithPattern(native int, native int, valuetype System.nfloat[])
	IL_0060: stfld native int CoreGraphics.CGColor::handle
	IL_0065: ldarg.0
	IL_0066: ldfld native int CoreGraphics.CGColor::handle
	IL_006b: ldsfld native int [mscorlib]System.IntPtr::Zero
	IL_0070: call bool [mscorlib]System.IntPtr::op_Equality(native int, native int)
	IL_0075: brfalse.s IL_007d

	IL_0077: newobj instance void [mscorlib]System.ArgumentException::.ctor()
	IL_007c: throw

	IL_007d: ret
} // end of method CGColor::.ctor
```

into

```
.method public hidebysig specialname rtspecialname
	instance void .ctor (
		class CoreGraphics.CGColorSpace colorspace,
		class CoreGraphics.CGPattern pattern,
		valuetype System.nfloat[] components
	) cil managed
{
	// Method begins at RVA 0x210660
	// Code size 119 (0x77)
	.maxstack 4
	.locals init (
		[0] native int handleof_pattern
	)

	IL_0000: ldarg.0
	IL_0001: call instance void [mscorlib]System.Object::.ctor()
	IL_0006: ldarg.1
	IL_0007: brtrue.s IL_0014

	IL_0009: ldstr "colorspace"
	IL_000e: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_0013: throw

	IL_0014: ldarg.1
	IL_0015: ldfld native int CoreGraphics.CGColorSpace::handle
	IL_001a: ldsfld native int [mscorlib]System.IntPtr::Zero
	IL_001f: call bool [mscorlib]System.IntPtr::op_Equality(native int, native int)
	IL_0024: brfalse.s IL_0031

	IL_0026: ldstr "colorspace"
	IL_002b: newobj instance void [mscorlib]System.ObjectDisposedException::.ctor(string)
	IL_0030: throw

	IL_0031: ldarg.3
	IL_0032: brtrue.s IL_003f

	IL_0034: ldstr "components"
	IL_0039: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
	IL_003e: throw

	IL_003f: ldarg.2
	IL_0040: ldstr "pattern"
	IL_0045: call native int ObjCRuntime.NativeObjectHelper::GetNonNullHandle(class ObjCRuntime.INativeObject, string)
	IL_004a: stloc.0
	IL_004b: ldarg.0
	IL_004c: ldarg.1
	IL_004d: ldfld native int CoreGraphics.CGColorSpace::handle
	IL_0052: ldloc.0
	IL_0053: ldarg.3
	IL_0054: call native int CoreGraphics.CGColor::CGColorCreateWithPattern(native int, native int, valuetype System.nfloat[])
	IL_0059: stfld native int CoreGraphics.CGColor::handle
	IL_005e: ldarg.0
	IL_005f: ldfld native int CoreGraphics.CGColor::handle
	IL_0064: ldsfld native int [mscorlib]System.IntPtr::Zero
	IL_0069: call bool [mscorlib]System.IntPtr::op_Equality(native int, native int)
	IL_006e: brfalse.s IL_0076

	IL_0070: newobj instance void [mscorlib]System.ArgumentException::.ctor()
	IL_0075: throw

	IL_0076: ret
} // end of method CGColor::.ctor
```

so the difference is smaller, but it's still smaller (7 bytes) than the
existing code (that did not check for a disposed instance).

There are many more optimizations that can be applied on top of this.
However the main/original goal is to have a correct and consistent
handling of disposed managed instances. IOW the size reduction is a nice
side-effect of correctness and actual optimizations can come later :)

Add `ObjectDisposedException` when required on Handle access.
Instead of providing `nil` to native API that are decorated **not**
accepting them.

Also do this using existing and new extension method helpers so the IL
size of the assemblies is (a bit) smaller than the existing code.

The latter has a small, positive impact for Xamarin.Mac (JIT'ing or
requiring IL for, non-full, AOT'ing) and for Xamarin.iOS when the
interpreter is used.
2020-10-30 13:02:15 -04:00
.github/workflows [Actions] Add debug for the workflow to find why it does not work with hub. (#10008) 2020-10-29 22:37:46 -04:00
builds [build] Implement support for optionally cache downloads in ~/Library/Caches/xamarin-macios. (#9894) 2020-10-19 10:50:27 +02:00
docs [xcode12] Rename master to main (#9631) 2020-09-15 07:09:29 -04:00
dotnet [dotnet] Don't try to include any results from the AOT compiler unless we're on a Mac. (#9989) 2020-10-30 07:48:34 +01:00
external Bump Xamarin.MacDev. Fixes #10003. (#10007) 2020-10-30 07:39:03 +01:00
fsharp Add config file for libmono-native dllmap 2019-03-13 00:34:47 +01:00
jenkins [dotnet] Package the workloads in a Windows installer (.msi) as well. (#9979) 2020-10-28 11:09:55 +01:00
mk [xcode12.1] Add ikvm-fork as a submodule instead of using the sources embedded in the mono archive. (#9776) (#9783) (#9888) 2020-10-15 16:19:49 -04:00
mono Add config file for libmono-native dllmap 2019-03-13 00:34:47 +01:00
msbuild [tests] Rewrite ValidateAppBundleTaskTests to not create a task in-process. (#9983) 2020-10-29 08:59:11 +01:00
opentk [xcode11] Stop building/shipping 32-bit Xamarin.Mac bits. Partial fix for #6300. (#6393) 2019-07-15 10:19:24 -07:00
runtime [dotnet] Fix install name for libxamarin[-debug].dylib on macOS (#9821) 2020-10-09 14:55:00 +02:00
src [objcruntime] Add helper to check for disposed instances (#8679) 2020-10-30 13:02:15 -04:00
tests [msbuild] Localization String Test for All Strings (#9971) 2020-10-30 10:19:55 -05:00
tools [compare-commits] Fix corruption in dotnet assemblies after API comparison. (#10011) 2020-10-30 14:36:21 +01:00
.editorconfig Add .editorconfig (#8058) 2020-03-10 11:24:46 -04:00
.gitignore [src] Build the .NET version of our product assemblies using a .NET 5 BCL. (#9637) 2020-09-21 13:22:44 +02:00
.gitmodules [xcode12.1] Add ikvm-fork as a submodule instead of using the sources embedded in the mono archive. (#9776) (#9783) (#9888) 2020-10-15 16:19:49 -04:00
CODEOWNERS [CODEOWNERS] Add the rightful owners of the device tests. (#8938) 2020-06-23 13:29:31 -04:00
ISSUE_TEMPLATE.md Instruction to find the build logs (#6871) 2019-08-29 10:42:14 -04:00
LICENSE Adjust license to match requested format 2016-04-25 16:38:57 -04:00
Make.config [Makefile] Point to xcode12.1 xip file. (#9973) 2020-10-27 17:22:53 -04:00
Make.versions [Main] Bring Xcode12.1 support. 2020-10-20 17:55:31 -04:00
Makefile [Xcode12] Bring xcode 12 changes into main. 2020-09-23 16:05:22 -04:00
NOTICE.txt Add NOTICE.txt and cgmanifest tool (#8843) 2020-06-12 14:30:21 -05:00
NuGet.config [src] Build the .NET version of our product assemblies using a .NET 5 BCL. (#9637) 2020-09-21 13:22:44 +02:00
README.md [README] Bump downloads to our new Xamarin.iOS stable (#9981) 2020-10-28 07:35:47 -04:00
SECURITY.MD Add SECURITY.MD to repo (as suggested by OSPO) (#7019) 2019-09-19 17:44:22 -04:00
Versions-ios.plist.in [xcode12.1] Bump for GM (#9876) 2020-10-14 20:06:20 -04:00
Versions-mac.plist.in [xcode12] Initial bump for Xcode 12 GM (#9644) 2020-09-16 11:41:44 +02:00
Xamarin.Mac.sln Fix path to dont link project in Xamarin.Mac.sln. (#8109) 2020-03-16 09:42:52 +01:00
Xamarin.iOS.sln [src] Use `Runtime.NSLog` instead of `System.Console.WriteLine` (#8626) 2020-05-20 13:38:44 -04:00
banner.png [README] Add Xamarin.iOS + Xamarin.Mac banner (#1665) 2017-02-08 17:42:48 -05:00
configure [DevOps] Add debugging messages from when we fail the ./configure (#9102) 2020-07-15 20:13:57 -04:00
mac-entitlements.plist Implement notarization. (#6928) 2019-09-09 00:34:11 -07:00
product.snk Add our mono runtimes to the build. 2016-04-24 14:47:24 -04:00
system-dependencies.sh [system-dependencies] Only use the locally installed .NET version. (#9885) 2020-10-16 08:23:22 +02:00
versions-check.csharp [Versions-ios.plist] watchOS started at 1.0 (#1328) 2016-12-13 10:52:58 +01:00

README.md

Xamarin.iOS + Xamarin.Mac logo

Xamarin.iOS & Xamarin.Mac

Welcome!

This module is the main repository for both Xamarin.iOS and Xamarin.Mac.

These SDKs allow us to create native iOS, tvOS, watchOS and macOS applications using the same UI controls we would in Objective-C and Xcode, except with the flexibility and elegance of a modern language (C#), the power of the .NET Base Class Library (BCL), and two first-class IDEs—Visual Studio for Mac and Visual Studio—at our fingertips.

This repository is where we do development for the Xamarin.iOS and Xamarin.Mac SDKs. There are a few ways that you can contribute, for example:

Contributing

If you are interested in fixing issues and contributing directly to the code base, please see the document How to Contribute, which covers the following:

Downloads

The preferred method for installing Xamarin.iOS and Mac is to use the Visual Studio installers (Windows, Mac).

The team also strongly recommends using the latest Xamarin SDK and Xcode whenever possible.

However, we provide links to older Xamarin.iOS and Mac packages for macOS downgrades and build machine configuration.

Version Xamarin.iOS Xamarin.Mac
d16.7 14.2.0.12 6.20.2.2
d16.6 13.18.2.1 6.18.2.1
d16.5 13.16.0.13 6.16.0.13
d16.4 13.10.0.21 6.10.0.21
d16.3 13.6.0.12 6.6.0.12
d16.2 12.14.0.114 5.14.0.114
d16.1 12.10.0.157 5.10.0.157
d16.0 12.8.0.2 5.8.0.0

Feedback

Discord

License

Copyright (c) .NET Foundation Contributors. All rights reserved. Licensed under the MIT License.