Fix callbacks on AOT
Summary: When using AOT mode on Mono one can't use instance methods for callbacks, the compiler needs the MonoPInvokeCallback attribute on a static method to know how to get back to the managed world. This worked fine without the change in JIT mode. I not sure if we should use a __MONO__ flag for this stuff as this could be needed for other usage that not only on iOS. ~~The adicional change is that one should as good practice call Dispose on the YogaNode when using callbacks to make sure we remove the handler from our dictionary, i was trying to write a test for this.. but i saw TestMeasureFuncWithDestructor was already there, but it doesn't seem correct to me, can you check splhack.~~ Closes https://github.com/facebook/yoga/pull/386 Reviewed By: emilsjolander Differential Revision: D4546030 Pulled By: splhack fbshipit-source-id: 121d44a2ecd14d754b9614493db6ac15fca02da2
This commit is contained in:
committed by
Facebook Github Bot
parent
2184547094
commit
8deed174f5
@@ -111,6 +111,13 @@ namespace Facebook.Yoga
|
|||||||
[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
|
||||||
|
@@ -8,17 +8,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
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 = null;
|
|
||||||
|
|
||||||
public static Func Logger = null;
|
public static Func Logger = null;
|
||||||
|
|
||||||
@@ -26,20 +23,27 @@ namespace Facebook.Yoga
|
|||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
{
|
{
|
||||||
_managedLogger = (level, message) => {
|
|
||||||
if (Logger != null)
|
|
||||||
{
|
|
||||||
Logger(level, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level == YogaLogLevel.Error)
|
Native.YGInteropSetLogger(LoggerInternal);
|
||||||
{
|
|
||||||
throw new InvalidOperationException(message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Native.YGInteropSetLogger(_managedLogger);
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __IOS__
|
||||||
|
[ObjCRuntime.MonoPInvokeCallback(typeof(Func))]
|
||||||
|
#endif
|
||||||
|
public static void LoggerInternal(YogaLogLevel level, string message)
|
||||||
|
{
|
||||||
|
if (Logger != null)
|
||||||
|
{
|
||||||
|
Logger(level, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == YogaLogLevel.Error)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
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;
|
||||||
|
|
||||||
namespace Facebook.Yoga
|
namespace Facebook.Yoga
|
||||||
@@ -544,7 +545,7 @@ namespace Facebook.Yoga
|
|||||||
{
|
{
|
||||||
while (_children.Count > 0)
|
while (_children.Count > 0)
|
||||||
{
|
{
|
||||||
RemoveAt(_children.Count-1);
|
RemoveAt(_children.Count - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -558,6 +559,10 @@ namespace Facebook.Yoga
|
|||||||
{
|
{
|
||||||
_measureFunction = measureFunction;
|
_measureFunction = measureFunction;
|
||||||
_ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null;
|
_ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null;
|
||||||
|
|
||||||
|
var handle = GCHandle.Alloc(this);
|
||||||
|
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
|
||||||
|
|
||||||
Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc);
|
Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,6 +570,10 @@ namespace Facebook.Yoga
|
|||||||
{
|
{
|
||||||
_baselineFunction = baselineFunction;
|
_baselineFunction = baselineFunction;
|
||||||
_ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null;
|
_ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null;
|
||||||
|
|
||||||
|
var handle = GCHandle.Alloc(this);
|
||||||
|
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
|
||||||
|
|
||||||
Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc);
|
Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,37 +586,55 @@ namespace Facebook.Yoga
|
|||||||
Native.YGNodeStyleGetDirection(_ygNode));
|
Native.YGNodeStyleGetDirection(_ygNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
private YogaSize MeasureInternal(
|
#if __IOS__
|
||||||
|
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))]
|
||||||
|
#endif
|
||||||
|
private static 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(this, width, widthMode, height, heightMode);
|
return measureFunction(yogaNode, width, widthMode, height, heightMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float BaselineInternal(IntPtr node, float width, float height)
|
|
||||||
|
#if __IOS__
|
||||||
|
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaBaselineFunc))]
|
||||||
|
#endif
|
||||||
|
private static float BaselineInternal(IntPtr node, float width, float height)
|
||||||
{
|
{
|
||||||
if (_baselineFunction == null)
|
var yogaNodePointer = Native.YGNodeGetContext(node);
|
||||||
|
|
||||||
|
YogaNode yogaNode = GCHandle.FromIntPtr(yogaNodePointer).Target as YogaNode;
|
||||||
|
|
||||||
|
var baselineFunction = yogaNode._baselineFunction;
|
||||||
|
if (baselineFunction == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Baseline function is not defined.");
|
throw new InvalidOperationException("Baseline function is not defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _baselineFunction(this, width, height);
|
return baselineFunction(yogaNode, 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