Fix callbacks on AOT
Summary: Based on the idea of #386 by rmarinho Closes https://github.com/facebook/yoga/pull/388 Reviewed By: emilsjolander Differential Revision: D4570778 Pulled By: splhack fbshipit-source-id: 362983deaf6f040c42b3db8205b711e7e5e60eaf
This commit is contained in:
committed by
Facebook Github Bot
parent
8deed174f5
commit
4fe0b810e1
@@ -22,6 +22,10 @@ namespace Facebook.Yoga
|
|||||||
|
|
||||||
internal class YGNodeHandle : SafeHandle
|
internal class YGNodeHandle : SafeHandle
|
||||||
{
|
{
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
|
private GCHandle _managed;
|
||||||
|
#endif
|
||||||
|
|
||||||
private YGNodeHandle() : base(IntPtr.Zero, true)
|
private YGNodeHandle() : base(IntPtr.Zero, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -36,10 +40,39 @@ namespace Facebook.Yoga
|
|||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
{
|
{
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
|
if (_managed.IsAllocated)
|
||||||
|
{
|
||||||
|
_managed.Free();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Native.YGNodeFree(this.handle);
|
Native.YGNodeFree(this.handle);
|
||||||
GC.KeepAlive(this);
|
GC.KeepAlive(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
|
public void SetContext(YogaNode node)
|
||||||
|
{
|
||||||
|
if (!_managed.IsAllocated)
|
||||||
|
{
|
||||||
|
_managed = GCHandle.Alloc(node, GCHandleType.Weak);
|
||||||
|
Native.YGNodeSetContext(this.handle, GCHandle.ToIntPtr(_managed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YogaNode GetManaged(IntPtr ygNodePtr)
|
||||||
|
{
|
||||||
|
var node =
|
||||||
|
GCHandle.FromIntPtr(Native.YGNodeGetContext(ygNodePtr)).Target as YogaNode;
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("YogaNode is already deallocated");
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
@@ -68,16 +101,20 @@ namespace Facebook.Yoga
|
|||||||
YogaExperimentalFeature feature);
|
YogaExperimentalFeature feature);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void YGNodeInsertChild(YGNodeHandle node, YGNodeHandle child, uint index);
|
public static extern void YGNodeInsertChild(
|
||||||
|
YGNodeHandle node,
|
||||||
|
YGNodeHandle child,
|
||||||
|
uint index);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void YGNodeRemoveChild(YGNodeHandle node, YGNodeHandle child);
|
public static extern void YGNodeRemoveChild(YGNodeHandle node, YGNodeHandle child);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void YGNodeCalculateLayout(YGNodeHandle node,
|
public static extern void YGNodeCalculateLayout(
|
||||||
float availableWidth,
|
YGNodeHandle node,
|
||||||
float availableHeight,
|
float availableWidth,
|
||||||
YogaDirection parentDirection);
|
float availableHeight,
|
||||||
|
YogaDirection parentDirection);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void YGNodeMarkDirty(YGNodeHandle node);
|
public static extern void YGNodeMarkDirty(YGNodeHandle node);
|
||||||
@@ -105,19 +142,14 @@ namespace Facebook.Yoga
|
|||||||
[MarshalAs(UnmanagedType.FunctionPtr)] YogaBaselineFunc baselineFunc);
|
[MarshalAs(UnmanagedType.FunctionPtr)] YogaBaselineFunc baselineFunc);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void YGNodeSetHasNewLayout(YGNodeHandle node, [MarshalAs(UnmanagedType.I1)] bool hasNewLayout);
|
public static extern void YGNodeSetHasNewLayout(
|
||||||
|
YGNodeHandle node,
|
||||||
|
[MarshalAs(UnmanagedType.I1)] bool hasNewLayout);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
[return: MarshalAs(UnmanagedType.I1)]
|
[return: MarshalAs(UnmanagedType.I1)]
|
||||||
public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node);
|
public static extern bool YGNodeGetHasNewLayout(YGNodeHandle node);
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
|
||||||
public static extern void YGNodeSetContext(YGNodeHandle node, IntPtr context);
|
|
||||||
|
|
||||||
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
|
||||||
public static extern IntPtr YGNodeGetContext(IntPtr node);
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region YG_NODE_STYLE_PROPERTY
|
#region YG_NODE_STYLE_PROPERTY
|
||||||
@@ -347,5 +379,17 @@ namespace Facebook.Yoga
|
|||||||
public static extern YogaDirection YGNodeLayoutGetDirection(YGNodeHandle node);
|
public static extern YogaDirection YGNodeLayoutGetDirection(YGNodeHandle node);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region IOS
|
||||||
|
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern IntPtr YGNodeGetContext(IntPtr node);
|
||||||
|
|
||||||
|
[DllImport(DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void YGNodeSetContext(IntPtr node, IntPtr managed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,29 +8,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
#if __IOS__
|
||||||
|
using ObjCRuntime;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Facebook.Yoga
|
namespace Facebook.Yoga
|
||||||
{
|
{
|
||||||
internal static class YogaLogger
|
internal static class YogaLogger
|
||||||
{
|
{
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void Func(YogaLogLevel level, string message);
|
public delegate void Func(YogaLogLevel level, string message);
|
||||||
|
|
||||||
private static bool _initialized;
|
private static bool _initialized;
|
||||||
|
private static Func _managedLogger = LoggerInternal;
|
||||||
|
|
||||||
public static Func Logger = null;
|
public static Func Logger = null;
|
||||||
|
|
||||||
public static void Initialize()
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
{
|
[MonoPInvokeCallback(typeof(Func))]
|
||||||
if (!_initialized)
|
|
||||||
{
|
|
||||||
|
|
||||||
Native.YGInteropSetLogger(LoggerInternal);
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __IOS__
|
|
||||||
[ObjCRuntime.MonoPInvokeCallback(typeof(Func))]
|
|
||||||
#endif
|
#endif
|
||||||
public static void LoggerInternal(YogaLogLevel level, string message)
|
public static void LoggerInternal(YogaLogLevel level, string message)
|
||||||
{
|
{
|
||||||
@@ -45,5 +42,13 @@ namespace Facebook.Yoga
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
if (!_initialized)
|
||||||
|
{
|
||||||
|
Native.YGInteropSetLogger(_managedLogger);
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,9 +10,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
#if __IOS__
|
||||||
|
using ObjCRuntime;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Facebook.Yoga
|
namespace Facebook.Yoga
|
||||||
{
|
{
|
||||||
public partial class YogaNode : IEnumerable<YogaNode>
|
public partial class YogaNode : IEnumerable<YogaNode>
|
||||||
@@ -21,10 +27,15 @@ namespace Facebook.Yoga
|
|||||||
private WeakReference _parent;
|
private WeakReference _parent;
|
||||||
private List<YogaNode> _children;
|
private List<YogaNode> _children;
|
||||||
private MeasureFunction _measureFunction;
|
private MeasureFunction _measureFunction;
|
||||||
private YogaMeasureFunc _ygMeasureFunc;
|
|
||||||
private BaselineFunction _baselineFunction;
|
private BaselineFunction _baselineFunction;
|
||||||
private YogaBaselineFunc _ygBaselineFunc;
|
|
||||||
private object _data;
|
private object _data;
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
|
private static YogaMeasureFunc _managedMeasure = MeasureInternalIOS;
|
||||||
|
private static YogaBaselineFunc _managedBaseline = BaselineInternalIOS;
|
||||||
|
#else
|
||||||
|
private YogaMeasureFunc _managedMeasure;
|
||||||
|
private YogaBaselineFunc _managedBaseline;
|
||||||
|
#endif
|
||||||
|
|
||||||
public YogaNode()
|
public YogaNode()
|
||||||
{
|
{
|
||||||
@@ -545,7 +556,7 @@ namespace Facebook.Yoga
|
|||||||
{
|
{
|
||||||
while (_children.Count > 0)
|
while (_children.Count > 0)
|
||||||
{
|
{
|
||||||
RemoveAt(_children.Count - 1);
|
RemoveAt(_children.Count-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -558,23 +569,29 @@ namespace Facebook.Yoga
|
|||||||
public void SetMeasureFunction(MeasureFunction measureFunction)
|
public void SetMeasureFunction(MeasureFunction measureFunction)
|
||||||
{
|
{
|
||||||
_measureFunction = measureFunction;
|
_measureFunction = measureFunction;
|
||||||
_ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null;
|
if (measureFunction != null)
|
||||||
|
{
|
||||||
var handle = GCHandle.Alloc(this);
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
|
_ygNode.SetContext(this);
|
||||||
|
#else
|
||||||
Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc);
|
_managedMeasure = MeasureInternal;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
Native.YGNodeSetMeasureFunc(_ygNode, _managedMeasure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBaselineFunction(BaselineFunction baselineFunction)
|
public void SetBaselineFunction(BaselineFunction baselineFunction)
|
||||||
{
|
{
|
||||||
_baselineFunction = baselineFunction;
|
_baselineFunction = baselineFunction;
|
||||||
_ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null;
|
if (baselineFunction != null)
|
||||||
|
{
|
||||||
var handle = GCHandle.Alloc(this);
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
|
_ygNode.SetContext(this);
|
||||||
|
#else
|
||||||
Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc);
|
_managedBaseline = BaselineInternal;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
Native.YGNodeSetBaselineFunc(_ygNode, _managedBaseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CalculateLayout()
|
public void CalculateLayout()
|
||||||
@@ -586,55 +603,63 @@ namespace Facebook.Yoga
|
|||||||
Native.YGNodeStyleGetDirection(_ygNode));
|
Native.YGNodeStyleGetDirection(_ygNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __IOS__
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))]
|
[MonoPInvokeCallback(typeof(YogaMeasureFunc))]
|
||||||
|
private static YogaSize MeasureInternalIOS(
|
||||||
|
IntPtr ygNodePtr,
|
||||||
|
float width,
|
||||||
|
YogaMeasureMode widthMode,
|
||||||
|
float height,
|
||||||
|
YogaMeasureMode heightMode)
|
||||||
|
{
|
||||||
|
var node = Native.YGNodeHandle.GetManaged(ygNodePtr);
|
||||||
|
return node.MeasureInternal(IntPtr.Zero, width, widthMode, height, heightMode);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
private static YogaSize MeasureInternal(
|
|
||||||
|
private YogaSize MeasureInternal(
|
||||||
IntPtr node,
|
IntPtr node,
|
||||||
float width,
|
float width,
|
||||||
YogaMeasureMode widthMode,
|
YogaMeasureMode widthMode,
|
||||||
float height,
|
float height,
|
||||||
YogaMeasureMode heightMode)
|
YogaMeasureMode heightMode)
|
||||||
{
|
{
|
||||||
|
if (_measureFunction == null)
|
||||||
var yogaNodePointer = Native.YGNodeGetContext(node);
|
|
||||||
|
|
||||||
YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode;
|
|
||||||
|
|
||||||
var measureFunction = yogaNode._measureFunction;
|
|
||||||
if (measureFunction == null)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Measure function is not defined.");
|
throw new InvalidOperationException("Measure function is not defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return measureFunction(yogaNode, width, widthMode, height, heightMode);
|
return _measureFunction(this, width, widthMode, height, heightMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (UNITY_IOS && !UNITY_EDITOR) || __IOS__
|
||||||
#if __IOS__
|
[MonoPInvokeCallback(typeof(YogaBaselineFunc))]
|
||||||
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaBaselineFunc))]
|
private static float BaselineInternalIOS(
|
||||||
#endif
|
IntPtr ygNodePtr,
|
||||||
private static float BaselineInternal(IntPtr node, float width, float height)
|
float width,
|
||||||
|
float height)
|
||||||
{
|
{
|
||||||
var yogaNodePointer = Native.YGNodeGetContext(node);
|
var node = Native.YGNodeHandle.GetManaged(ygNodePtr);
|
||||||
|
return node.BaselineInternal(IntPtr.Zero, width, height);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode;
|
private float BaselineInternal(IntPtr node, float width, float height)
|
||||||
|
{
|
||||||
var baselineFunction = yogaNode._baselineFunction;
|
if (_baselineFunction == null)
|
||||||
if (baselineFunction == null)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Baseline function is not defined.");
|
throw new InvalidOperationException("Baseline function is not defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return baselineFunction(yogaNode, width, height);
|
return _baselineFunction(this, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Print(YogaPrintOptions options =
|
public string Print(YogaPrintOptions options =
|
||||||
YogaPrintOptions.Layout | YogaPrintOptions.Style | YogaPrintOptions.Children)
|
YogaPrintOptions.Layout|YogaPrintOptions.Style|YogaPrintOptions.Children)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
YogaLogger.Func orig = YogaLogger.Logger;
|
YogaLogger.Func orig = YogaLogger.Logger;
|
||||||
YogaLogger.Logger = (level, message) => { sb.Append(message); };
|
YogaLogger.Logger = (level, message) => {sb.Append(message);};
|
||||||
Native.YGNodePrint(_ygNode, options);
|
Native.YGNodePrint(_ygNode, options);
|
||||||
YogaLogger.Logger = orig;
|
YogaLogger.Logger = orig;
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
Reference in New Issue
Block a user