Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
19f8278
Use InteropReferences for type enumeration
Sergio0694 Feb 5, 2026
5ecb9ab
Handle SZ array types in interop discovery
Sergio0694 Feb 5, 2026
27a3944
Track SZ array types and refine discovery
Sergio0694 Feb 5, 2026
08e29f9
Refactor SZ array tracking and discovery
Sergio0694 Feb 5, 2026
71e2d16
Use SzArrayTypeSignature as key for _szArrayTypes
Sergio0694 Feb 5, 2026
add0b3b
Fix Windows Runtime array type check
Sergio0694 Feb 5, 2026
47c29c6
Expose SZ array vtable mappings and collections
Sergio0694 Feb 5, 2026
3f74496
Detect duplicate GeneratedComInterface IIDs
Sergio0694 Feb 5, 2026
bd13054
Support explicit IMarshal and split entries
Sergio0694 Feb 5, 2026
9acf0a8
Add interop interface entries resolver
Sergio0694 Feb 5, 2026
7ce898e
Separate metadata/native interface enumeration
Sergio0694 Feb 5, 2026
cb1c7d8
Use InteropInterfaceEntriesResolver for entries
Sergio0694 Feb 5, 2026
132f366
Validate implTypes length matches entries fields
Sergio0694 Feb 6, 2026
1c5e6e3
Centralize native COM interface entries
Sergio0694 Feb 6, 2026
1f4d9cb
Add SZ array COM interface entries support
Sergio0694 Feb 6, 2026
4214e95
Add OrderByFullyQualifiedTypeName extension
Sergio0694 Feb 6, 2026
e87afca
Order CCW types by fully qualified name
Sergio0694 Feb 6, 2026
5cee02c
Add Create factory to InteropInterfaceEntries
Sergio0694 Feb 6, 2026
19078e0
Use thread-static list for SZ array entries
Sergio0694 Feb 6, 2026
2f31756
Remove IReferenceArray entries and szArray caching
Sergio0694 Feb 6, 2026
910a0b5
Fix comment grammar and XML doc spacing
Sergio0694 Feb 6, 2026
f946062
Use SzArrayInterfaceEntries and update discovery
Sergio0694 Feb 6, 2026
eb67eac
Handle overridable WinRT interfaces in discovery
Sergio0694 Feb 7, 2026
4d836d3
Merge branch 'staging/3.0' into user/sergiopedri/sz-array-ccw
manodasanW Feb 7, 2026
b9b395e
Fix spacing
manodasanW Feb 7, 2026
1805b90
Order TypeSignatures before computing hash
Sergio0694 Feb 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using AsmResolver.DotNet;
using AsmResolver.DotNet.Code.Cil;
Expand All @@ -10,6 +12,7 @@
using WindowsRuntime.InteropGenerator.Factories;
using WindowsRuntime.InteropGenerator.Generation;
using WindowsRuntime.InteropGenerator.Helpers;
using WindowsRuntime.InteropGenerator.Models;
using WindowsRuntime.InteropGenerator.References;
using WindowsRuntime.InteropGenerator.Resolvers;
using static AsmResolver.PE.DotNet.Cil.CilOpCodes;
Expand All @@ -26,6 +29,12 @@ internal partial class InteropTypeDefinitionBuilder
/// </summary>
public static class SzArray
{
/// <summary>
/// The thread-local list to build COM interface entries.
/// </summary>
[ThreadStatic]
private static List<InteropInterfaceEntryInfo>? entriesList;

/// <summary>
/// Creates a new type definition for the marshaller for some SZ array type.
/// </summary>
Expand Down Expand Up @@ -335,82 +344,75 @@ public static void ArrayImpl(
/// Creates a new type definition for the implementation of the COM interface entries for some SZ array type.
/// </summary>
/// <param name="arrayType">The <see cref="SzArrayTypeSignature"/> for the SZ array type.</param>
/// <param name="vtableTypes">The vtable types implemented by <paramref name="arrayType"/>.</param>
/// <param name="implType">The <see cref="TypeDefinition"/> instance returned by <see cref="Impl"/>.</param>
/// <param name="get_IidMethod">The 'IID' get method for the 'IReferenceArray`1&lt;T&gt;' interface.</param>
/// <param name="interopDefinitions">The <see cref="InteropDefinitions"/> instance to use.</param>
/// <param name="interopReferences">The <see cref="InteropReferences"/> instance to use.</param>
/// <param name="emitState">The emit state for this invocation.</param>
/// <param name="module">The module that will contain the type being created.</param>
/// <param name="useWindowsUIXamlProjections">Whether to use <c>Windows.UI.Xaml</c> projections.</param>
/// <param name="interfaceEntriesType">The resulting interface entries type.</param>
/// <param name="interfaceEntriesImplType">The resulting implementation type.</param>
public static void InterfaceEntriesImpl(
SzArrayTypeSignature arrayType,
TypeSignatureEquatableSet vtableTypes,
TypeDefinition implType,
MethodDefinition get_IidMethod,
InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
InteropGeneratorEmitState emitState,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
out TypeDefinition interfaceEntriesType,
out TypeDefinition interfaceEntriesImplType)
{
var listImpl = InteropImplTypeResolver.GetCustomMappedOrManuallyProjectedTypeImpl(
type: interopReferences.IList.ToReferenceTypeSignature(),
interopReferences: interopReferences,
useWindowsUIXamlProjections: useWindowsUIXamlProjections);
// Reuse the same list, to minimize allocations (same as for user-defined types)
List<InteropInterfaceEntryInfo> entriesList = SzArray.entriesList ??= [];

var enumerableImpl = InteropImplTypeResolver.GetCustomMappedOrManuallyProjectedTypeImpl(
type: interopReferences.IEnumerable.ToReferenceTypeSignature(),
interopReferences: interopReferences,
useWindowsUIXamlProjections: useWindowsUIXamlProjections);

var list1Impl = InteropImplTypeResolver.GetGenericInstanceTypeImpl(
type: interopReferences.IList1.MakeGenericReferenceType(arrayType.BaseType),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
emitState: emitState);
// It's not guaranteed that the list is empty, so we must always reset it first
entriesList.Clear();

var enumerable1Impl = InteropImplTypeResolver.GetGenericInstanceTypeImpl(
type: interopReferences.IEnumerable1.MakeGenericReferenceType(arrayType.BaseType),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
emitState: emitState);
// Add the entry for the 'IReferenceArray<T>' implementation first
entriesList.Add(InteropInterfaceEntriesResolver.Create(get_IidMethod, implType.GetMethod("get_Vtable"u8)));

var readOnlyList1Impl = InteropImplTypeResolver.GetGenericInstanceTypeImpl(
type: interopReferences.IReadOnlyList1.MakeGenericReferenceType(arrayType.BaseType),
// Add all entries for explicitly implemented interfaces
entriesList.AddRange(InteropInterfaceEntriesResolver.EnumerateMetadataInterfaceEntries(
vtableTypes: vtableTypes,
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
emitState: emitState);
emitState: emitState,
module: module,
useWindowsUIXamlProjections: useWindowsUIXamlProjections));

var propertyValueImpl = InteropImplTypeResolver.GetSzArrayTypeImpl(arrayType, interopReferences);

// Add the entry for the 'IPropertyValue' implementation as well
entriesList.Add(InteropInterfaceEntriesResolver.Create(propertyValueImpl.get_IID, propertyValueImpl.get_Vtable));

// Add the built-in native interfaces at the end
entriesList.AddRange(InteropInterfaceEntriesResolver.EnumerateNativeInterfaceEntries(
vtableTypes: vtableTypes,
interopReferences: interopReferences));

// Get or create the interface entries type for this SZ array type (we reuse them based on number of entries)
interfaceEntriesType = interopDefinitions.SzArrayInterfaceEntries(entriesList.Count);

InteropTypeDefinitionBuilder.InterfaceEntriesImpl(
ns: InteropUtf8NameFactory.TypeNamespace(arrayType),
name: InteropUtf8NameFactory.TypeName(arrayType, "InterfaceEntriesImpl"),
entriesFieldType: interopDefinitions.IReferenceArrayInterfaceEntries,
entriesFieldType: interfaceEntriesType,
interopReferences: interopReferences,
module: module,
implType: out interfaceEntriesImplType,
implTypes: [
(get_IidMethod, implType.GetMethod("get_Vtable"u8)),
(listImpl.get_IID, listImpl.get_Vtable),
(enumerableImpl.get_IID, enumerableImpl.get_Vtable),
(list1Impl.get_IID, list1Impl.get_Vtable),
(enumerable1Impl.get_IID, enumerable1Impl.get_Vtable),
(readOnlyList1Impl.get_IID, readOnlyList1Impl.get_Vtable),
(propertyValueImpl.get_IID, propertyValueImpl.get_Vtable),
(interopReferences.WellKnownInterfaceIIDsget_IID_IStringable, interopReferences.IStringableImplget_Vtable),
(interopReferences.WellKnownInterfaceIIDsget_IID_IWeakReferenceSource, interopReferences.IWeakReferenceSourceImplget_Vtable),
(interopReferences.WellKnownInterfaceIIDsget_IID_IMarshal, interopReferences.IMarshalImplget_Vtable),
(interopReferences.WellKnownInterfaceIIDsget_IID_IAgileObject, interopReferences.IAgileObjectImplget_Vtable),
(interopReferences.WellKnownInterfaceIIDsget_IID_IInspectable, interopReferences.IInspectableImplget_Vtable),
(interopReferences.WellKnownInterfaceIIDsget_IID_IUnknown, interopReferences.IUnknownImplget_Vtable)]);
implTypes: CollectionsMarshal.AsSpan(entriesList));
}

/// <summary>
/// Creates a new type definition for the marshaller attribute for some SZ array type.
/// </summary>
/// <param name="arrayType">The <see cref="SzArrayTypeSignature"/> for the SZ array type.</param>
/// <param name="arrayInterfaceEntriesType">The <see cref="TypeDefinition"/> for the interface entries type returned by <see cref="InterfaceEntriesImpl"/>.</param>
/// <param name="arrayInterfaceEntriesImplType">The <see cref="TypeDefinition"/> instance returned by <see cref="InterfaceEntriesImpl"/>.</param>
/// <param name="arrayComWrappersCallbackType">The <see cref="TypeDefinition"/> instance returned by <see cref="ComWrappersCallback"/>.</param>
/// <param name="get_IidMethod">The 'IID' get method for the 'IReferenceArray`1&lt;T&gt;' interface.</param>
Expand All @@ -420,6 +422,7 @@ public static void InterfaceEntriesImpl(
/// <param name="marshallerType">The resulting marshaller type.</param>
public static void ComWrappersMarshallerAttribute(
SzArrayTypeSignature arrayType,
TypeDefinition arrayInterfaceEntriesType,
TypeDefinition arrayInterfaceEntriesImplType,
TypeDefinition arrayComWrappersCallbackType,
MethodDefinition get_IidMethod,
Expand Down Expand Up @@ -482,7 +485,7 @@ public static void ComWrappersMarshallerAttribute(
CilInstructions =
{
{ Ldarg_1 },
{ CilInstruction.CreateLdcI4(interopDefinitions.IReferenceArrayInterfaceEntries.Fields.Count) },
{ CilInstruction.CreateLdcI4(arrayInterfaceEntriesType.Fields.Count) },
{ Stind_I4 },
{ Call, arrayInterfaceEntriesImplType.GetMethod("get_Vtables"u8) },
{ Ret }
Expand Down
Loading