diff --git a/runtime/monotouch-support.h b/runtime/monotouch-support.h
index 845bebcc0047..e5c14a3dee2f 100644
--- a/runtime/monotouch-support.h
+++ b/runtime/monotouch-support.h
@@ -1,4 +1,4 @@
-#ifndef __MONOTOUCH_SUPPORT_H__
+#ifndef __MONOTOUCH_SUPPORT_H__
#define __MONOTOUCH_SUPPORT_H__
#ifdef __cplusplus
@@ -15,6 +15,11 @@ void xamarin_start_wwan (const char *uri);
const char * xamarin_GetFolderPath (int folder);
#endif
+#ifdef MONOMAC
+const char *
+xamarin_encode_CGAffineTransform ();
+#endif
+
#if defined (__arm64__)
void objc_msgSend_stret (void);
void objc_msgSendSuper_stret (void);
diff --git a/runtime/xamarin-support.m b/runtime/xamarin-support.m
index 72dc38e7aee7..cf86a990cdeb 100644
--- a/runtime/xamarin-support.m
+++ b/runtime/xamarin-support.m
@@ -172,3 +172,13 @@ void objc_msgSendSuper_stret (void)
#endif
+#ifdef MONOMAC
+// Do not hard-code this parameter as a C string.
+// works on iOS (where we don't need it) and crash on macOS
+const char *
+xamarin_encode_CGAffineTransform ()
+{
+ // COOP: no managed memory access: any mode.
+ return @encode (CGAffineTransform);
+}
+#endif
diff --git a/src/Foundation/NSValue.cs b/src/Foundation/NSValue.cs
index 38a25e071d02..dd9c0efa7320 100644
--- a/src/Foundation/NSValue.cs
+++ b/src/Foundation/NSValue.cs
@@ -1,6 +1,7 @@
//
// Copyright 2010, Novell, Inc.
// Copyright 2011, 2012, 2013 Xamarin Inc
+// Copyright 2019 Microsoft Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -22,11 +23,14 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
#if !NO_SYSTEM_DRAWING
using System.Drawing;
#endif
using System.Runtime.InteropServices;
+using CoreGraphics;
+
namespace Foundation {
public partial class NSValue : NSObject {
#if !COREBUILD
@@ -64,6 +68,31 @@ public PointF PointFValue {
get { return (PointF)CGPointValue; }
}
#endif
+
+#if MONOMAC
+ // @encode(CGAffineTransform) -> "{CGAffineTransform=dddddd}" but...
+ // using a C string crash on macOS (while it works fine on iOS)
+ [DllImport ("__Internal")]
+ extern static IntPtr xamarin_encode_CGAffineTransform ();
+
+ // The `+valueWithCGAffineTransform:` selector comes from UIKit and is not available on macOS
+ public unsafe static NSValue FromCGAffineTransform (CGAffineTransform tran)
+ {
+ return Create ((IntPtr) (void*) &tran, xamarin_encode_CGAffineTransform ());
+ }
+
+ // The `CGAffineTransformValue` selector comes from UIKit and is not available on macOS
+ public unsafe virtual CGAffineTransform CGAffineTransformValue {
+ get {
+ var result = new CGAffineTransform ();
+ // avoid potential buffer overflow since we use the older `getValue:` API to cover all platforms
+ // and we can cheat here with the actual string comparison (since we are the one doing it)
+ if (ObjCType == "{CGAffineTransform=dddddd}")
+ StoreValueAtAddress ((IntPtr) (void*) &result);
+ return result;
+ }
+ }
+#endif
#endif
}
}
diff --git a/src/foundation.cs b/src/foundation.cs
index 3dc2839b7b8b..6d8262eace06 100644
--- a/src/foundation.cs
+++ b/src/foundation.cs
@@ -10879,14 +10879,19 @@ partial interface NSValue : NSSecureCoding, NSCopying {
[Export ("getValue:")]
void StoreValueAtAddress (IntPtr value);
+ [Watch (4,0), TV (11,0), Mac (10,13), iOS (11,0)]
+ [Export ("getValue:size:")]
+ void StoreValueAtAddress (IntPtr value, nuint size);
+
[Export ("objCType")][Internal]
IntPtr ObjCTypePtr ();
//[Export ("initWithBytes:objCType:")][Internal]
//NSValue InitFromBytes (IntPtr byte_ptr, IntPtr char_ptr_type);
- //[Export ("valueWithBytes:objCType:")][Static][Internal]
- //+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;
- //+ (NSValue *)value:(const void *)value withObjCType:(const char *)type;
+
+ [Static][Internal]
+ [Export ("valueWithBytes:objCType:")]
+ NSValue Create (IntPtr bytes, IntPtr objCType);
[Static]
[Export ("valueWithNonretainedObject:")]
diff --git a/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs b/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs
index 5f2e2014800f..fb477cef4d3d 100644
--- a/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs
+++ b/tests/monotouch-test/CoreGraphics/AffineTransformTest.cs
@@ -5,6 +5,7 @@
// Rolf Bjarne Kvinge
//
// Copyright 2014 Xamarin Inc. All rights reserved.
+// Copyright 2019 Microsoft Corporation
//
using System;
@@ -334,6 +335,22 @@ public void Invert ()
Assert.AreEqual ((nfloat) 1.0, transform.x0, "x0");
Assert.AreEqual ((nfloat) (-2.0), transform.y0, "y0");
}
+
+ [Test]
+ public void NSValueRoundtrip ()
+ {
+ var transform = new CGAffineTransform (1, 2, 3, 4, 5, 6);
+ // looks simplistic but that NSValue logic is implemented by "us" on macOS
+ using (var nsv = NSValue.FromCGAffineTransform (transform)) {
+ var tback = nsv.CGAffineTransformValue;
+ Assert.AreEqual ((nfloat)1, tback.xx, "xx");
+ Assert.AreEqual ((nfloat)2, tback.yx, "yx");
+ Assert.AreEqual ((nfloat)3, tback.xy, "xy");
+ Assert.AreEqual ((nfloat)4, tback.yy, "yy");
+ Assert.AreEqual ((nfloat)5, tback.x0, "x0");
+ Assert.AreEqual ((nfloat)6, tback.y0, "y0");
+ }
+ }
}
diff --git a/tests/xtro-sharpie/common-Foundation.ignore b/tests/xtro-sharpie/common-Foundation.ignore
index d7d33c9f3787..23b9a2916cc1 100644
--- a/tests/xtro-sharpie/common-Foundation.ignore
+++ b/tests/xtro-sharpie/common-Foundation.ignore
@@ -417,7 +417,6 @@
!missing-selector! +NSURLRequest::requestWithURL:cachePolicy:timeoutInterval: not bound
!missing-selector! +NSURLRequest::supportsSecureCoding not bound
!missing-selector! +NSValue::value:withObjCType: not bound
-!missing-selector! +NSValue::valueWithBytes:objCType: not bound
!missing-selector! +NSXPCInterface::interfaceWithProtocol: not bound
!missing-selector! NSArray::addObserver:forKeyPath:options:context: not bound
!missing-selector! NSArray::arrayByAddingObject: not bound
@@ -837,7 +836,6 @@
!missing-selector! NSURLProtocol::task not bound
!missing-selector! NSURLRequest::HTTPShouldUsePipelining not bound
!missing-selector! NSUUID::initWithUUIDBytes: not bound
-!missing-selector! NSValue::getValue:size: not bound
!missing-selector! NSValue::initWithBytes:objCType: not bound
!missing-selector! NSXPCConnection::auditSessionIdentifier not bound
!missing-selector! NSXPCConnection::effectiveGroupIdentifier not bound