[csharp,iOS] Fix callbacks on AOT #386

Closed
rmarinho wants to merge 6 commits from fix-logger-xamarinios into master
3 changed files with 61 additions and 23 deletions

View File

@@ -111,6 +111,13 @@ namespace Facebook.Yoga
[return: MarshalAs(UnmanagedType.I1)]
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
#region YG_NODE_STYLE_PROPERTY

View File

@@ -8,17 +8,14 @@
*/
using System;
using System.Runtime.InteropServices;
namespace Facebook.Yoga
{
internal static class YogaLogger
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Func(YogaLogLevel level, string message);
private static bool _initialized;
private static Func _managedLogger = null;
public static Func Logger = null;
@@ -26,7 +23,17 @@ namespace Facebook.Yoga
{
if (!_initialized)
{
_managedLogger = (level, message) => {
Native.YGInteropSetLogger(LoggerInternal);
_initialized = true;
}
}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(Func))]
#endif
public static void LoggerInternal(YogaLogLevel level, string message)
{
if (Logger != null)
{
Logger(level, message);
@@ -36,10 +43,7 @@ namespace Facebook.Yoga
{
throw new InvalidOperationException(message);
}
};
Native.YGInteropSetLogger(_managedLogger);
_initialized = true;
}
}
}
}
}

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
@@ -546,6 +547,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);
}
@@ -553,6 +558,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);
}
@@ -565,29 +574,47 @@ namespace Facebook.Yoga
Native.YGNodeStyleGetDirection(_ygNode));
}
private YogaSize MeasureInternal(
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(YogaMeasureFunc))]
#endif
rolfbjarne commented 2017-02-13 00:16:55 -08:00 (Migrated from github.com)
Review

Your patch never calls GCHandle.Free.

Also you allocate a GCHandle both SetMeasureFunction and SetBaselineFunction, if both are called one of the values stored with YGNodeSetContext will be overwritten. The same will happen if either function is called more than once.

Your patch never calls `GCHandle.Free`. Also you allocate a GCHandle both SetMeasureFunction and SetBaselineFunction, if both are called one of the values stored with YGNodeSetContext will be overwritten. The same will happen if either function is called more than once.
rmarinho commented 2017-02-13 02:34:15 -08:00 (Migrated from github.com)
Review

@splhack pr #388 fixes this.

@splhack pr #388 fixes this.
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 =