From 35da310736f72ccbd8d8f3a6187c2238598cc767 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 13 Jan 2026 10:23:52 +0100 Subject: [PATCH 1/2] [Foundation] Improve NSArray.FromIntPtrs slightly. * Enable nullability. * Simplify code, with both reduced memory footprint, and faster execution speed. * Add tests. * Add xml docs. --- src/Foundation/NSArray.cs | 24 +++++++------- .../monotouch-test/Foundation/NSArray1Test.cs | 32 +++++++++++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/Foundation/NSArray.cs b/src/Foundation/NSArray.cs index 245dad2a4218..7b676efabe5b 100644 --- a/src/Foundation/NSArray.cs +++ b/src/Foundation/NSArray.cs @@ -283,6 +283,7 @@ static public NSArray FromStrings (IReadOnlyList items) } } +#nullable enable /// Create an from the specified pointers. /// Array of pointers (to instances). /// If the array is null, an is thrown. @@ -293,24 +294,25 @@ static internal NSArray FromIntPtrs (IntPtr [] items) unsafe { fixed (IntPtr* valuesPtr = items) - return Runtime.GetNSObject (NSArray.FromObjects ((IntPtr) valuesPtr, items.Length))!; + return Runtime.GetNSObject (NSArray.FromObjects ((IntPtr) valuesPtr, items.Length)) ?? new NSArray (); } } - static public NSArray FromIntPtrs (NativeHandle [] vals) + /// Create an from the specified pointers. + /// Array of pointers (to instances). + /// If the array is null, an is thrown. + public static NSArray FromIntPtrs (NativeHandle [] vals) { if (vals is null) - throw new ArgumentNullException ("vals"); - int n = vals.Length; - IntPtr buf = Marshal.AllocHGlobal (n * IntPtr.Size); - for (int i = 0; i < n; i++) - Marshal.WriteIntPtr (buf, i * IntPtr.Size, vals [i]); - - NSArray arr = Runtime.GetNSObject (NSArray.FromObjects (buf, vals.Length)); + throw new ArgumentNullException (nameof (vals)); - Marshal.FreeHGlobal (buf); - return arr; + unsafe { + fixed (NativeHandle* valuesPtr = vals) { + return Runtime.GetNSObject (NSArray.FromObjects ((IntPtr) valuesPtr, vals.Length)) ?? new NSArray (); + } + } } +#nullable disable internal static nuint GetCount (IntPtr handle) { diff --git a/tests/monotouch-test/Foundation/NSArray1Test.cs b/tests/monotouch-test/Foundation/NSArray1Test.cs index 78e7b4b90745..3afb37a706a6 100644 --- a/tests/monotouch-test/Foundation/NSArray1Test.cs +++ b/tests/monotouch-test/Foundation/NSArray1Test.cs @@ -125,6 +125,38 @@ public void ToArray_T () } } + [Test] + public void FromIntPtrs_NativeHandle () + { + var str1 = (NSString) "1"; + var str2 = (NSString) "2"; + var str3 = (NSString) "3"; + + var handles = new NativeHandle [] { str1.Handle, str2.Handle, str3.Handle }; + using (var arr = NSArray.FromIntPtrs (handles)) { + Assert.AreEqual ((nuint) 3, arr.Count, "NSArray Count"); + Assert.AreEqual ("1", arr.GetItem (0).ToString (), "NSArray item 0"); + Assert.AreEqual ("2", arr.GetItem (1).ToString (), "NSArray item 1"); + Assert.AreEqual ("3", arr.GetItem (2).ToString (), "NSArray item 2"); + } + } + + [Test] + public void FromIntPtrs_NativeHandle_Null () + { + NativeHandle []? handles = null; + Assert.Throws (() => NSArray.FromIntPtrs (handles!), "Null array"); + } + + [Test] + public void FromIntPtrs_NativeHandle_Empty () + { + var handles = new NativeHandle [0]; + using (var arr = NSArray.FromIntPtrs (handles)) { + Assert.AreEqual ((nuint) 0, arr.Count, "NSArray Count"); + } + } + #if false // https://github.com/dotnet/macios/issues/15577 [Test] public void GetDifferenceFromArrayTest () From bf6ce57a446a377270db273e88dd068f7e9e494c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 14 Jan 2026 09:39:19 +0100 Subject: [PATCH 2/2] Documented --- tests/cecil-tests/Documentation.KnownFailures.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt index 304a5515b88e..c0bedcdbd785 100644 --- a/tests/cecil-tests/Documentation.KnownFailures.txt +++ b/tests/cecil-tests/Documentation.KnownFailures.txt @@ -11806,7 +11806,6 @@ M:Foundation.INSUrlSessionWebSocketDelegate.DidOpen(Foundation.NSUrlSession,Foun M:Foundation.INSXpcListenerDelegate.ShouldAcceptConnection(Foundation.NSXpcListener,Foundation.NSXpcConnection) M:Foundation.NSArray.ArrayFromHandle``1(ObjCRuntime.NativeHandle,System.Converter{ObjCRuntime.NativeHandle,``0},System.Boolean) M:Foundation.NSArray.EnumsFromHandle``1(ObjCRuntime.NativeHandle) -M:Foundation.NSArray.FromIntPtrs(ObjCRuntime.NativeHandle[]) M:Foundation.NSArray.FromNSObjects``1(``0[][]) M:Foundation.NSArray.FromNSObjects``1(``0[0:,0:]) M:Foundation.NSArray.FromStrings(System.Collections.Generic.IReadOnlyList{System.String})