From 04f97c9923156b0c695f5fe441ffd14624de8076 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 5 Apr 2019 12:52:00 -0700 Subject: Enable return buffers on Windows ARM64 for struct-returning member functions (#23625) * Enable return buffers on Windows ARM64 for struct-returning member functions. Fixes #23577. * Update comment to match new condition. * Enable byref return on all Windows (excluding arm64 HFA. Add more test cases for ThisCall. * On x86, if we have a normalized return value in an instance method, get back the actual type so that we correctly marshal it via a return buffer. * Fix param ordering. * Clean up based on PR feedback. * Fix accidental variable shadowing. --- .../Miscellaneous/ThisCall/ThisCallNative.cpp | 20 ++++++++ .../PInvoke/Miscellaneous/ThisCall/ThisCallTest.cs | 57 +++++++++++++++++++--- 2 files changed, 69 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallNative.cpp b/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallNative.cpp index 9f1d56ccb9..3424dbf20a 100644 --- a/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallNative.cpp +++ b/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallNative.cpp @@ -12,6 +12,16 @@ struct SizeF float height; }; +struct Width +{ + float width; +}; + +struct IntWrapper +{ + int i; +}; + class C { int dummy = 0xcccccccc; @@ -28,6 +38,16 @@ public: { return {width, height}; } + + virtual Width GetWidth() + { + return {width}; + } + + virtual IntWrapper GetHeightAsInt() + { + return {(int)height}; + } }; diff --git a/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallTest.cs b/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallTest.cs index ea7b7dacc3..a39a0fa128 100644 --- a/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallTest.cs +++ b/tests/src/Interop/PInvoke/Miscellaneous/ThisCall/ThisCallTest.cs @@ -15,12 +15,14 @@ unsafe class ThisCallNative public struct VtableLayout { public IntPtr getSize; + public IntPtr getWidth; + public IntPtr getHeightAsInt; } public VtableLayout* vtable; private int c; - private float width; - private float height; + public readonly float width; + public readonly float height; } public struct SizeF @@ -29,8 +31,22 @@ unsafe class ThisCallNative public float height; } + public struct Width + { + public float width; + } + + public struct IntWrapper + { + public int i; + } + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] public delegate SizeF GetSizeFn(C* c); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate Width GetWidthFn(C* c); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + public delegate IntWrapper GetHeightAsIntFn(C* c); [DllImport(nameof(ThisCallNative))] public static extern C* CreateInstanceOfC(float width, float height); @@ -45,12 +61,9 @@ class ThisCallTest float width = 1.0f; float height = 2.0f; ThisCallNative.C* instance = ThisCallNative.CreateInstanceOfC(width, height); - ThisCallNative.GetSizeFn callback = Marshal.GetDelegateForFunctionPointer(instance->vtable->getSize); - - ThisCallNative.SizeF result = callback(instance); - - Assert.AreEqual(width, result.width); - Assert.AreEqual(height, result.height); + Test8ByteHFA(instance); + Test4ByteHFA(instance); + Test4ByteNonHFA(instance); } catch (System.Exception ex) { @@ -59,4 +72,32 @@ class ThisCallTest } return 100; } + + private static unsafe void Test8ByteHFA(ThisCallNative.C* instance) + { + ThisCallNative.GetSizeFn callback = Marshal.GetDelegateForFunctionPointer(instance->vtable->getSize); + + ThisCallNative.SizeF result = callback(instance); + + Assert.AreEqual(instance->width, result.width); + Assert.AreEqual(instance->height, result.height); + } + + private static unsafe void Test4ByteHFA(ThisCallNative.C* instance) + { + ThisCallNative.GetWidthFn callback = Marshal.GetDelegateForFunctionPointer(instance->vtable->getWidth); + + ThisCallNative.Width result = callback(instance); + + Assert.AreEqual(instance->width, result.width); + } + + private static unsafe void Test4ByteNonHFA(ThisCallNative.C* instance) + { + ThisCallNative.GetHeightAsIntFn callback = Marshal.GetDelegateForFunctionPointer(instance->vtable->getHeightAsInt); + + ThisCallNative.IntWrapper result = callback(instance); + + Assert.AreEqual((int)instance->height, result.i); + } } -- cgit v1.2.3