Files
yoga/csharp/Facebook.Yoga/YogaNode.Spacing.cs
Eric Rozell 5bc0197c78 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
2017-03-06 11:42:40 -08:00

554 lines
13 KiB
C#

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.Yoga
{
public partial class YogaNode
{
public YogaValue Left
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Left));
}
set
{
SetStylePosition(YogaEdge.Left, value);
}
}
public YogaValue Top
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Top));
}
set
{
SetStylePosition(YogaEdge.Top, value);
}
}
public YogaValue Right
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Right));
}
set
{
SetStylePosition(YogaEdge.Right, value);
}
}
public YogaValue Bottom
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Bottom));
}
set
{
SetStylePosition(YogaEdge.Bottom, value);
}
}
public YogaValue Start
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.Start));
}
set
{
SetStylePosition(YogaEdge.Start, value);
}
}
public YogaValue End
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPosition(_ygNode, YogaEdge.End));
}
set
{
SetStylePosition(YogaEdge.End, value);
}
}
private void SetStylePosition(YogaEdge edge, YogaValue value)
{
if (value.Unit == YogaUnit.Percent)
{
Native.YGNodeStyleSetPositionPercent(_ygNode, edge, value.Value);
}
else
{
Native.YGNodeStyleSetPosition(_ygNode, edge, value.Value);
}
}
public YogaValue MarginLeft
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Left));
}
set
{
SetStyleMargin(YogaEdge.Left, value);
}
}
public YogaValue MarginTop
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Top));
}
set
{
SetStyleMargin(YogaEdge.Top, value);
}
}
public YogaValue MarginRight
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Right));
}
set
{
SetStyleMargin(YogaEdge.Right, value);
}
}
public YogaValue MarginBottom
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Bottom));
}
set
{
SetStyleMargin(YogaEdge.Bottom, value);
}
}
public YogaValue MarginStart
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Start));
}
set
{
SetStyleMargin(YogaEdge.Start, value);
}
}
public YogaValue MarginEnd
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.End));
}
set
{
SetStyleMargin(YogaEdge.End, value);
}
}
public YogaValue MarginHorizontal
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Horizontal));
}
set
{
SetStyleMargin(YogaEdge.Horizontal, value);
}
}
public YogaValue MarginVertical
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.Vertical));
}
set
{
SetStyleMargin(YogaEdge.Vertical, value);
}
}
public YogaValue Margin
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetMargin(_ygNode, YogaEdge.All));
}
set
{
SetStyleMargin(YogaEdge.All, value);
}
}
private void SetStyleMargin(YogaEdge edge, YogaValue value)
{
if (value.Unit == YogaUnit.Percent)
{
Native.YGNodeStyleSetMarginPercent(_ygNode, edge, value.Value);
}
else if (value.Unit == YogaUnit.Auto)
{
Native.YGNodeStyleSetMarginAuto(_ygNode, edge);
}
else
{
Native.YGNodeStyleSetMargin(_ygNode, edge, value.Value);
}
}
public YogaValue PaddingLeft
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Left));
}
set
{
SetStylePadding(YogaEdge.Left, value);
}
}
public YogaValue PaddingTop
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Top));
}
set
{
SetStylePadding(YogaEdge.Top, value);
}
}
public YogaValue PaddingRight
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Right));
}
set
{
SetStylePadding(YogaEdge.Right, value);
}
}
public YogaValue PaddingBottom
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Bottom));
}
set
{
SetStylePadding(YogaEdge.Bottom, value);
}
}
public YogaValue PaddingStart
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Start));
}
set
{
SetStylePadding(YogaEdge.Start, value);
}
}
public YogaValue PaddingEnd
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.End));
}
set
{
SetStylePadding(YogaEdge.End, value);
}
}
public YogaValue PaddingHorizontal
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Horizontal));
}
set
{
SetStylePadding(YogaEdge.Horizontal, value);
}
}
public YogaValue PaddingVertical
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.Vertical));
}
set
{
SetStylePadding(YogaEdge.Vertical, value);
}
}
public YogaValue Padding
{
get
{
return YogaValue.MarshalValue(Native.YGNodeStyleGetPadding(_ygNode, YogaEdge.All));
}
set
{
SetStylePadding(YogaEdge.All, value);
}
}
private void SetStylePadding(YogaEdge edge, YogaValue value)
{
if (value.Unit == YogaUnit.Percent)
{
Native.YGNodeStyleSetPaddingPercent(_ygNode, edge, value.Value);
}
else
{
Native.YGNodeStyleSetPadding(_ygNode, edge, value.Value);
}
}
public float BorderLeftWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.Left);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.Left, value);
}
}
public float BorderTopWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.Top);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.Top, value);
}
}
public float BorderRightWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.Right);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.Right, value);
}
}
public float BorderBottomWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.Bottom);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.Bottom, value);
}
}
public float BorderStartWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.Start);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.Start, value);
}
}
public float BorderEndWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.End);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.End, value);
}
}
public float BorderWidth
{
get
{
return Native.YGNodeStyleGetBorder(_ygNode, YogaEdge.All);
}
set
{
Native.YGNodeStyleSetBorder(_ygNode, YogaEdge.All, value);
}
}
public float LayoutMarginLeft
{
get
{
return Native.YGNodeLayoutGetMargin(_ygNode, YogaEdge.Left);
}
}
public float LayoutMarginTop
{
get
{
return Native.YGNodeLayoutGetMargin(_ygNode, YogaEdge.Top);
}
}
public float LayoutMarginRight
{
get
{
return Native.YGNodeLayoutGetMargin(_ygNode, YogaEdge.Right);
}
}
public float LayoutMarginBottom
{
get
{
return Native.YGNodeLayoutGetMargin(_ygNode, YogaEdge.Bottom);
}
}
public float LayoutMarginStart
{
get
{
return Native.YGNodeLayoutGetMargin(_ygNode, YogaEdge.Start);
}
}
public float LayoutMarginEnd
{
get
{
return Native.YGNodeLayoutGetMargin(_ygNode, YogaEdge.End);
}
}
public float LayoutPaddingLeft
{
get
{
return Native.YGNodeLayoutGetPadding(_ygNode, YogaEdge.Left);
}
}
public float LayoutPaddingTop
{
get
{
return Native.YGNodeLayoutGetPadding(_ygNode, YogaEdge.Top);
}
}
public float LayoutPaddingRight
{
get
{
return Native.YGNodeLayoutGetPadding(_ygNode, YogaEdge.Right);
}
}
public float LayoutPaddingBottom
{
get
{
return Native.YGNodeLayoutGetPadding(_ygNode, YogaEdge.Bottom);
}
}
public float LayoutPaddingStart
{
get
{
return Native.YGNodeLayoutGetPadding(_ygNode, YogaEdge.Start);
}
}
public float LayoutPaddingEnd
{
get
{
return Native.YGNodeLayoutGetPadding(_ygNode, YogaEdge.End);
}
}
}
}