[csharp,iOS] Fix callbacks on AOT #386

Closed
rmarinho wants to merge 6 commits from fix-logger-xamarinios into master
3 changed files with 65 additions and 9 deletions
Showing only changes of commit f90633cec5 - Show all commits

View File

@@ -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

View File

@@ -37,9 +37,31 @@ namespace Facebook.Yoga
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
}; };
#if __IOS__
Native.YGInteropSetLogger(ManagedLogger);
#else
rolfbjarne commented 2017-02-13 00:11:20 -08:00 (Migrated from github.com)
Review

You need to store the delegate in a static field, otherwise the GC will collect it and the app will crash when the callback is called:

static Func _logger_internal = LoggerInternal;

Native.YGInteropSetLogger (_logger_internal);
You need to store the delegate in a static field, otherwise the GC will collect it and the app will crash when the callback is called: static Func _logger_internal = LoggerInternal; Native.YGInteropSetLogger (_logger_internal);
rmarinho commented 2017-02-13 02:33:47 -08:00 (Migrated from github.com)
Review

@splhack can you take a note on this in your PR ?

@splhack can you take a note on this in your PR ?
splhack commented 2017-02-13 08:40:37 -08:00 (Migrated from github.com)
Review

sure

sure
Native.YGInteropSetLogger(_managedLogger); Native.YGInteropSetLogger(_managedLogger);
#endif
_initialized = true; _initialized = true;
} }
} }
#if __IOS__
delegate void ManagedLoggerCallback(YogaLogLevel level, string message);
[ObjCRuntime.MonoPInvokeCallback(typeof(ManagedLoggerCallback))]
public static void ManagedLogger(YogaLogLevel level, string message)
{
if (Logger != null)
{
Logger(level, message);
}
if (level == YogaLogLevel.Error)
{
throw new InvalidOperationException(message);
}
}
#endif
} }
} }

View File

@@ -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
@@ -546,6 +547,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);
} }
@@ -553,6 +558,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);
} }
@@ -565,29 +574,47 @@ namespace Facebook.Yoga
Native.YGNodeStyleGetDirection(_ygNode)); 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, 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 =