From dd5798b57b7ed6d162e2f6805ec74f4759a98e6a Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Mon, 6 Mar 2017 11:29:52 -0800 Subject: [PATCH] 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 --- ReactCommon/yoga/yoga/YGMacros.h | 8 ++++++++ ReactCommon/yoga/yoga/Yoga.c | 4 ++-- ReactCommon/yoga/yoga/Yoga.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGMacros.h b/ReactCommon/yoga/yoga/YGMacros.h index 10580db5e..2d8f72868 100644 --- a/ReactCommon/yoga/yoga/YGMacros.h +++ b/ReactCommon/yoga/yoga/YGMacros.h @@ -23,6 +23,14 @@ #define WIN_EXPORT #endif +#ifdef WINARMDLL +#define WIN_STRUCT(type) type* +#define WIN_STRUCT_REF(value) &value +#else +#define WIN_STRUCT(type) type +#define WIN_STRUCT_REF(value) value +#endif + #ifndef FB_ASSERTIONS_ENABLED #define FB_ASSERTIONS_ENABLED 1 #endif diff --git a/ReactCommon/yoga/yoga/Yoga.c b/ReactCommon/yoga/yoga/Yoga.c index 7338319ea..6d7595b63 100644 --- a/ReactCommon/yoga/yoga/Yoga.c +++ b/ReactCommon/yoga/yoga/Yoga.c @@ -613,8 +613,8 @@ static inline const YGValue *YGNodeResolveFlexBasisPtr(const YGNodeRef node) { } \ } \ \ - type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ - return node->style.instanceName[edge]; \ + WIN_STRUCT(type) YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge) { \ + return WIN_STRUCT_REF(node->style.instanceName[edge]); \ } #define YG_NODE_STYLE_EDGE_PROPERTY_IMPL(type, name, paramName, instanceName) \ diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index 3b3b84a9d..e7a71a97b 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -141,7 +141,7 @@ WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, \ const YGEdge edge, \ const float paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); + WIN_EXPORT WIN_STRUCT(type) YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \ WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge);