Skip to content

Marshalling IEnumerable<T> in modern UWP fails #1839

@devsko

Description

@devsko

Describe the bug
Calling WinRT with parameters of type IEnumerable<T> in modern UWP fails with various exceptions depending on T and parameter type.

To Reproduce

  1. Create a new .NET 9 UWP project
  2. Add <WindowsSDKPackageVersion>10.0.26100.54</WindowsSDKPackageVersion> and <AllowUnsafeBlocks>true</AllowUnsafeBlocks> to .csproj
  3. Add a Page_Loaded handler to MainPage with this code:
            new Geopath([new BasicGeoposition(0, 0, 0)]); // BasicGeoposition is a value type
            // System.InvalidCastException: Specified cast is not valid.
            //    at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
            //    at WinRT.ComWrappersSupport.CreateCCWForObjectForABI(Object obj, Guid iid)
            //    at WinRT.ComWrappersSupport.CreateCCWForObjectForMarshaling(Object obj, Guid iid)
            //    at WinRT.MarshalInspectable`1.CreateMarshaler2(T o, Guid iid, Boolean unwrapObject)
            //    at WinRT.MarshalInterface`1.CreateMarshaler2(T value, Guid iid)
            //    at Windows.Devices.Geolocation.Geopath._IGeopathFactoryMethods.Create(IObjectReference _obj, IEnumerable`1 positions)
            //    at Windows.Devices.Geolocation.Geopath..ctor(IEnumerable`1 positions)

            new Geopath(new BasicGeoposition[] { new(0, 0, 0) });
            // System.NotSupportedException: Cannot provide IReferenceArray`1 support for element type 'Windows.Devices.Geolocation.BasicGeoposition'.
            //    at WinRT.ComWrappersSupport.ProvideIReferenceArray(Type arrayType)
            //    at WinRT.ComWrappersSupport.GetInterfaceTableEntries(Type type)
            //    at WinRT.DefaultComWrappers.<>c.<ComputeVtables>b__7_0(Type type)
            //    at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValueLocked(TKey key, CreateValueCallback createValueCallback)
            //    at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
            //    at WinRT.DefaultComWrappers.ComputeVtables(Object obj, CreateComInterfaceFlags flags, Int32& count)
            //    at System.Runtime.InteropServices.ComWrappers.TryGetOrCreateComInterfaceForObjectInternal(ObjectHandleOnStack comWrappersImpl, Int64 wrapperId, ObjectHandleOnStack instance, CreateComInterfaceFlags flags, IntPtr& retValue)
            //    at System.Runtime.InteropServices.ComWrappers.TryGetOrCreateComInterfaceForObjectInternal(ComWrappers impl, Object instance, CreateComInterfaceFlags flags, IntPtr& retValue)
            //    at System.Runtime.InteropServices.ComWrappers.GetOrCreateComInterfaceForObject(Object instance, CreateComInterfaceFlags flags)
            //    at WinRT.ComWrappersSupport.CreateCCWForObjectForABI(Object obj, Guid iid)
            //    at WinRT.ComWrappersSupport.CreateCCWForObjectForMarshaling(Object obj, Guid iid)
            //    at WinRT.MarshalInspectable`1.CreateMarshaler2(T o, Guid iid, Boolean unwrapObject)
            //    at WinRT.MarshalInterface`1.CreateMarshaler2(T value, Guid iid)
            //    at Windows.Devices.Geolocation.Geopath._IGeopathFactoryMethods.Create(IObjectReference _obj, IEnumerable`1 positions)
            //    at Windows.Devices.Geolocation.Geopath..ctor(IEnumerable`1 positions)

            MapStyleSheet.Combine([MapStyleSheet.Aerial()]); // MapStyleSheet is a reference type
            // System.InvalidCastException: Specified cast is not valid.
            //    at WinRT.ComWrappersSupport.CreateCCWForObjectForABI(Object obj, Guid iid)
            //    at WinRT.ComWrappersSupport.CreateCCWForObjectForMarshaling(Object obj, Guid iid)
            //    at WinRT.MarshalInspectable`1.CreateMarshaler2(T o, Guid iid, Boolean unwrapObject)
            //    at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
            //    at WinRT.MarshalInterface`1.CreateMarshaler2(T value, Guid iid)
            //    at ABI.Windows.UI.Xaml.Controls.Maps.IMapStyleSheetStaticsMethods.Combine(IObjectReference _obj, IEnumerable`1 styleSheets)
            //    at Windows.UI.Xaml.Controls.Maps.MapStyleSheet.Combine(IEnumerable`1 styleSheets)

            MapStyleSheet.Combine(new MapStyleSheet[] { MapStyleSheet.Aerial() }); 
            // works when AllowUnsafeBlocks=true, InvalidCastException otherwise

Expected behavior

No exceptions

Version Info

net9.0 rc2, Windows SDK 26100

Additional context

Creating a Geopath in WinUI3 works as expected. (MapStyleSheet is not available in WinUI3)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions