Workaround for P/Invoke AccessViolationException

Summary:
The issue is on ARM builds for Windows UWP. For the C# P/Invoke API wrapper, any native method that returns the YogaValue struct throws the AccessViolationException. The issue is not with structs in general, as returning the YogaSize / YGSize struct works fine. The issue seems to be limited to structs that have an enum member.

I tried a number of things to resolve the issue without changing the underlying native API for Windows. I read the ARM documentation and saw reference to variable enum sizes based on the number of enum members, so I tried to use a number of different UnmanagedType values in a [MarsalAs()] attribute on the enum member of the C# struct declaration.

What ultimately worked was to return a pointer to the location of the struct, and use the System.Runtime.InteropServices.PtrToStructure API to read the struct data from that pointer. I added a few new macros that will return the struct address on Windows only, other builds are not affected.

Note, I have not tested the impact of this ch
Closes https://github.com/facebook/yoga/pull/459

Reviewed By: emilsjolander

Differential Revision: D4652278

Pulled By: splhack

fbshipit-source-id: bf7ada4da1781e3f813b3ba331974b7bded476d9
This commit is contained in:
Eric Rozell
2017-03-06 11:29:52 -08:00
committed by Facebook Github Bot
parent 62f47190fb
commit 5bc0197c78
9 changed files with 102 additions and 78 deletions

View File

@@ -12,6 +12,12 @@ using System.Runtime.InteropServices;
namespace Facebook.Yoga
{
#if WINDOWS_UWP_ARM
using YogaValueType = IntPtr;
#else
using YogaValueType = YogaValue;
#endif
internal static class Native
{
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
@@ -172,7 +178,7 @@ namespace Facebook.Yoga
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeCopyStyle(YGNodeHandle dstNode, YGNodeHandle srcNode);
#region YG_NODE_PROPERTY
#region YG_NODE_PROPERTY
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeSetMeasureFunc(
@@ -193,9 +199,9 @@ namespace Facebook.Yoga
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node);
#endregion
#endregion
#region YG_NODE_STYLE_PROPERTY
#region YG_NODE_STYLE_PROPERTY
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetDirection(YGNodeHandle node, YogaDirection direction);
@@ -282,7 +288,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetFlexBasisAuto(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetFlexBasis(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetFlexBasis(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetWidth(YGNodeHandle node, float width);
@@ -294,7 +300,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetWidthAuto(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetWidth(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetHeight(YGNodeHandle node, float height);
@@ -306,7 +312,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetHeightAuto(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetHeight(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMinWidth(YGNodeHandle node, float minWidth);
@@ -315,7 +321,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetMinWidthPercent(YGNodeHandle node, float minWidth);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetMinWidth(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetMinWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMinHeight(YGNodeHandle node, float minHeight);
@@ -324,7 +330,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetMinHeightPercent(YGNodeHandle node, float minHeight);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetMinHeight(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetMinHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMaxWidth(YGNodeHandle node, float maxWidth);
@@ -333,7 +339,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetMaxWidthPercent(YGNodeHandle node, float maxWidth);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetMaxWidth(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetMaxWidth(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMaxHeight(YGNodeHandle node, float maxHeight);
@@ -342,7 +348,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetMaxHeightPercent(YGNodeHandle node, float maxHeight);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetMaxHeight(YGNodeHandle node);
public static extern YogaValueType YGNodeStyleGetMaxHeight(YGNodeHandle node);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetAspectRatio(YGNodeHandle node, float aspectRatio);
@@ -350,9 +356,9 @@ namespace Facebook.Yoga
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeStyleGetAspectRatio(YGNodeHandle node);
#endregion
#endregion
#region YG_NODE_STYLE_EDGE_PROPERTY
#region YG_NODE_STYLE_EDGE_PROPERTY
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPosition(YGNodeHandle node, YogaEdge edge, float position);
@@ -361,7 +367,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetPositionPercent(YGNodeHandle node, YogaEdge edge, float position);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge);
public static extern YogaValueType YGNodeStyleGetPosition(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetMargin(YGNodeHandle node, YogaEdge edge, float margin);
@@ -373,7 +379,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetMarginAuto(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge);
public static extern YogaValueType YGNodeStyleGetMargin(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetPadding(YGNodeHandle node, YogaEdge edge, float padding);
@@ -382,7 +388,7 @@ namespace Facebook.Yoga
public static extern void YGNodeStyleSetPaddingPercent(YGNodeHandle node, YogaEdge edge, float padding);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaValue YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge);
public static extern YogaValueType YGNodeStyleGetPadding(YGNodeHandle node, YogaEdge edge);
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern void YGNodeStyleSetBorder(YGNodeHandle node, YogaEdge edge, float border);
@@ -390,9 +396,9 @@ namespace Facebook.Yoga
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeStyleGetBorder(YGNodeHandle node, YogaEdge edge);
#endregion
#endregion
#region YG_NODE_LAYOUT_PROPERTY
#region YG_NODE_LAYOUT_PROPERTY
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern float YGNodeLayoutGetLeft(YGNodeHandle node);
@@ -421,9 +427,9 @@ namespace Facebook.Yoga
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern YogaDirection YGNodeLayoutGetDirection(YGNodeHandle node);
#endregion
#endregion
#region IOS
#region IOS
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
@@ -433,6 +439,6 @@ namespace Facebook.Yoga
public static extern void YGNodeSetContext(IntPtr node, IntPtr managed);
#endif
#endregion
#endregion
}
}

View File

@@ -7,8 +7,6 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System;
namespace Facebook.Yoga
{
public partial class YogaNode
@@ -17,7 +15,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Left);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Left));
}
set
@@ -30,7 +28,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Top);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Top));
}
set
@@ -43,7 +41,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Right);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Right));
}
set
@@ -56,7 +54,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Bottom);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Bottom));
}
set
@@ -69,7 +67,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Start);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Start));
}
set
@@ -82,7 +80,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.End);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.End));
}
set
@@ -107,7 +105,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Left);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Left));
}
set
@@ -120,7 +118,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Top);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Top));
}
set
@@ -133,7 +131,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Right);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Right));
}
set
@@ -146,7 +144,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Bottom);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Bottom));
}
set
@@ -159,7 +157,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Start);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Start));
}
set
@@ -172,7 +170,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.End);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.End));
}
set
@@ -185,7 +183,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Horizontal);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Horizontal));
}
set
@@ -198,7 +196,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Vertical);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Vertical));
}
set
@@ -211,7 +209,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.All);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.All));
}
set
@@ -240,7 +238,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Left);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Left));
}
set
@@ -253,7 +251,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Top);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Top));
}
set
@@ -266,7 +264,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Right);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Right));
}
set
@@ -279,7 +277,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Bottom);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Bottom));
}
set
@@ -292,7 +290,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Start);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Start));
}
set
@@ -305,7 +303,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.End);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.End));
}
set
@@ -318,7 +316,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Horizontal);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Horizontal));
}
set
@@ -331,7 +329,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Vertical);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Vertical));
}
set
@@ -344,7 +342,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.All);
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.All));
}
set

View File

@@ -318,7 +318,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetFlexBasis(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetFlexBasis(_ygNode));
}
set
@@ -342,7 +342,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetWidth(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetWidth(_ygNode));
}
set
@@ -366,7 +366,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetHeight(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetHeight(_ygNode));
}
set
@@ -390,7 +390,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMaxWidth(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMaxWidth(_ygNode));
}
set
@@ -410,7 +410,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMaxHeight(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMaxHeight(_ygNode));
}
set
@@ -430,7 +430,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMinWidth(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMinWidth(_ygNode));
}
set
@@ -450,7 +450,7 @@ namespace Facebook.Yoga
{
get
{
return Native.YGNodeStyleGetMinHeight(_ygNode);
return YogaValue.MarshalValue(Native.YGNodeStyleGetMinHeight(_ygNode));
}
set

View File

@@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
using System;
using System.Runtime.InteropServices;
namespace Facebook.Yoga
@@ -92,5 +93,17 @@ namespace Facebook.Yoga
{
return Point(pointValue);
}
#if WINDOWS_UWP_ARM
internal static YogaValue MarshalValue(IntPtr ptr)
{
return Marshal.PtrToStructure<YogaValue>(ptr);
}
#else
internal static YogaValue MarshalValue(YogaValue value)
{
return value;
}
#endif
}
}