microsoft / Win2D

Win2D is an easy-to-use Windows Runtime API for immediate mode 2D graphics rendering with GPU acceleration. It is available to C#, C++ and VB developers writing apps for the Windows Universal Platform (UWP). It utilizes the power of Direct2D, and integrates seamlessly with XAML and CoreWindow.
http://microsoft.github.io/Win2D
Other
1.81k stars 285 forks source link

MissingInteropDataException when using CanvasTextAnalyzer.GetGlyphs on .NET Native #666

Open Mailosz opened 5 years ago

Mailosz commented 5 years ago

Hi, I have application that works fine when I disable .NET Native but gets exception when .NET Native is enabled.

The problem is a single call to GetGlyphs method of CanvasTextAnalyzer. The exception I get is this:

System.Runtime.InteropServices.MissingInteropDataException: 'Windows.Foundation.Collections.IKeyValuePair`2[Microsoft.Graphics.Canvas.Text.CanvasCharacterRange,Microsoft.Graphics.Canvas.Text.CanvasTypography] is missing interop type marshalling data. To enable interop type marshalling data, add a MarshalObject directive to the application rd.xml file. For more information, please visit http://go.microsoft.com/fwlink/?LinkID=393965'

So I get that the problem is that type List<KeyValuePair<CanvasCharacterRange, CanvasTypography>> doesn't have runtime directive somewhere. I've heard that I could add it myself to my project, and I tried, but unfortunately I was not able to do it. Nevertheless, I think that this should work "out of box" and that this is bug.

Top of my stack: at System.Runtime.InteropServices.__interface_ccw.Allocate(ComCallableObject managedCCW, RuntimeTypeHandle typeHandle) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\ComCallableObject.cs:line 133 at System.Runtime.InteropServices.ComCallableObject.AddFirstType_NoAddRef(RuntimeTypeHandle typeHandle, Guid& guid) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\ComCallableObject.cs:line 1615 at System.Runtime.InteropServices.CCWLookupMap.GetOrCreateCCW(Object target, RuntimeTypeHandle typeHandle, IntPtr& interfaceCCW) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\ComCallableObject.cs:line 915 at System.Runtime.InteropServices.McgComHelpers.ManagedObjectToComInterfaceInternal(Object obj, Guid& iid, RuntimeTypeHandle interfaceType) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\McgComHelpers.cs:line 832 at System.Runtime.InteropServices.McgComHelpers.ManagedObjectToComInterface(Object obj, RuntimeTypeHandle interfaceType) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\McgComHelpers.cs:line 802 at System.Runtime.InteropServices.McgMarshal.ManagedObjectToComInterface(Object obj, RuntimeTypeHandle interfaceType) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\McgMarshal.cs:line 870 at System.Collections.Generic.IReadOnlyList_A__scg_KeyValuePair_A_Microsoft_Graphics_Canvas_Text_CanvasCharacterRange_j_Microsoft_Graphics_Canvas_Text_CanvasTypography_V__V___Impl.Vtbl.GetAt__n(IntPtr pComThis, UInt32 unsafe_index, Void** unsafe___value__retval) at System.Runtime.InteropServices.McgMarshal.ThrowOnExternalCallFailed(Int32 hr, RuntimeTypeHandle typeHnd) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.Interop\src\Shared\McgMarshal.cs:line 1021 at __Interop.ComCallHelpers.Call(__ComObject __this, RuntimeTypeHandle __typeHnd, Int32 __targetIndex, CanvasCharacterRange arg0, Void* arg1, Single arg2, SByte arg3, SByte arg4, CanvasAnalyzedScript arg5, HSTRING arg6, Void* arg7, Void* arg8, Void* arg9, Void* arg10, Void* arg11, Void* arg12, Void* arg13, Void* arg14, Void* arg15, Void* arg16) at Microsoft.Graphics.Canvas.Text.ICanvasTextAnalyzer__Impl.Stubs.GetGlyphs(__ComObject __this, CanvasCharacterRange characterRange, CanvasFontFace fontFace, Single fontSize, Boolean isSideways, Boolean isRightToLeft, CanvasAnalyzedScript script, String locale, CanvasNumberSubstitution numberSubstitution, IReadOnlyList`1 typographyRanges, Int32[]& clusterMapIndicesElements, Boolean[]& isShapedAloneGlyphsElements, CanvasGlyphShaping[]& glyphShapingResultsElements) at Microsoft.Graphics.Canvas.Text.CanvasTextAnalyzer.GetGlyphs(CanvasCharacterRange characterRange, CanvasFontFace fontFace, Single fontSize, Boolean isSideways, Boolean isRightToLeft, CanvasAnalyzedScript script, String locale, CanvasNumberSubstitution numberSubstitution, IReadOnlyList`1 typographyRanges, Int32[]& clusterMapIndicesElements, Boolean[]& isShapedAloneGlyphsElements, CanvasGlyphShaping[]& glyphShapingResultsElements)

Thanks in advance for your reply!

MattWhilden commented 5 years ago

I work on the .NET Native team and would like to take a look at resolving this issue. I'll likely have time tomorrow to dig into it. I'll try to repro it myself but often the fastest way to get things taken care if is if you can send us an ilcRepro file.

MattWhilden commented 5 years ago

Alright, I'm not too proud to acknowledge when I can't seem to get things set up correctly. Either I don't have things configured as you do or I've misunderstood the issue entirely. Any chance someone can help a poor compiler dev out and share a repro project or an ilcRepro file?

Mailosz commented 5 years ago

BugRepro.zip

Hi, thanks for looking into this issue. I created new simple project that illustrates the problem. The following program runs well in debug mode (without .Native) but throws MissingInteropDataException on line 52 in MainPage.xaml.cs when running on Release mode (with .NET Native turned on).

Hope this will help you reproduce the issue.

MattWhilden commented 5 years ago

Greatly appreciated. I can reproduce the issue as reported. I'll take a look today or early tomorrow and let you know. Most of the time there's a easy workaround but we won't know 'til we know...

MattWhilden commented 5 years ago

Good news! There's a single line workaround that should get you back on your feet. Adding the line below to Properties\Default.rd.xml file causes the error to disappear. <Type Name="System.Collections.Generic.KeyValuePair{Microsoft.Graphics.Canvas.Text.CanvasCharacterRange, Microsoft.Graphics.Canvas.Text.CanvasTypography}" MarshalObject="Required All" /> We'll still want to chase down exactly why this doesn't get automatically picked up by the compiler and your intuition that this is expected to work "out of the box" is spot on. The issue presents itself for every version of the compiler I had immediately on hand so it's likely this never worked quite right for this case. I'll cut a bug internally and see about getting it patched up.

If this becomes more of an issue for folks using Win2D, it's possible for the library to package an .rd.xml file into the nuget package with this directive.

Thanks again for the report. Let me know if the workaround doesn't match up for you or if there are other issues.