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:
Rui Marinho
2017-02-16 11:07:50 -08:00
committed by Facebook Github Bot
parent 2184547094
commit 8deed174f5
3 changed files with 61 additions and 23 deletions

View File

@@ -10,6 +10,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Facebook.Yoga
@@ -544,7 +545,7 @@ namespace Facebook.Yoga
{
while (_children.Count > 0)
{
RemoveAt(_children.Count-1);
RemoveAt(_children.Count - 1);
}
}
}
@@ -558,6 +559,10 @@ namespace Facebook.Yoga
{
_measureFunction = measureFunction;
_ygMeasureFunc = measureFunction != null ? MeasureInternal : (YogaMeasureFunc)null;
var handle = GCHandle.Alloc(this);
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
Native.YGNodeSetMeasureFunc(_ygNode, _ygMeasureFunc);
}
@@ -565,6 +570,10 @@ namespace Facebook.Yoga
{
_baselineFunction = baselineFunction;
_ygBaselineFunc = baselineFunction != null ? BaselineInternal : (YogaBaselineFunc)null;
var handle = GCHandle.Alloc(this);
Native.YGNodeSetContext(_ygNode, GCHandle.ToIntPtr(handle));
Native.YGNodeSetBaselineFunc(_ygNode, _ygBaselineFunc);
}
@@ -577,37 +586,55 @@ namespace Facebook.Yoga
Native.YGNodeStyleGetDirection(_ygNode));
}
private YogaSize MeasureInternal(
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))]
#endif
private static YogaSize MeasureInternal(
IntPtr node,
float width,
YogaMeasureMode widthMode,
float height,
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.");
}
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.");
}
return _baselineFunction(this, width, height);
return baselineFunction(yogaNode, width, height);
}
public string Print(YogaPrintOptions options =
YogaPrintOptions.Layout|YogaPrintOptions.Style|YogaPrintOptions.Children)
YogaPrintOptions.Layout | YogaPrintOptions.Style | YogaPrintOptions.Children)
{
StringBuilder sb = new StringBuilder();
YogaLogger.Func orig = YogaLogger.Logger;
YogaLogger.Logger = (level, message) => {sb.Append(message);};
YogaLogger.Logger = (level, message) => { sb.Append(message); };
Native.YGNodePrint(_ygNode, options);
YogaLogger.Logger = orig;
return sb.ToString();