}
}
-public interface IUnmanagedVirtualMethodTableProvider<T> where T : IEquatable<T>
+public interface IUnmanagedVirtualMethodTableProvider
{
- protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey);
+ protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type);
public sealed VirtualMethodTableInfo GetVirtualMethodTableInfoForKey<TUnmanagedInterfaceType>()
- where TUnmanagedInterfaceType : IUnmanagedInterfaceType<T>
+ where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
- return GetVirtualMethodTableInfoForKey(TUnmanagedInterfaceType.TypeKey);
+ // Dispatch from a non-virtual generic to a virtual non-generic with System.Type
+ // to avoid generic virtual method dispatch, which is very slow.
+ return GetVirtualMethodTableInfoForKey(typeof(TUnmanagedInterfaceType));
}
}
-public interface IUnmanagedInterfaceType<T> where T : IEquatable<T>
+public interface IUnmanagedInterfaceType<TUnmanagedInterfaceType> where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
- public abstract static T TypeKey { get; }
}
```
## Required API Shapes
-The user will be required to implement `IUnmanagedVirtualMethodTableProvider<T>` on the type that provides the method tables, and `IUnmanagedInterfaceType<T>` on the type that defines the unmanaged interface. The `T` types must match between the two interfaces. This mechanism is designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`.
+The user will be required to implement `IUnmanagedVirtualMethodTableProvider` on the type that provides the method tables, and `IUnmanagedInterfaceType<TUnmanagedInterfaceType>` on the type that defines the unmanaged interface. The `TUnmanagedInterfaceType` follows the same design principles as the generic math designs as somewhat of a "self" type to enable us to use the derived interface type in any additional APIs we add to support unmanaged-to-managed stubs.
+
+Previously, each of these interface types were also generic on another type `T`. The `T` types were required to match between the two interfaces. This mechanism was designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`. However, practical implementation showed that providing just a "type key" was not enough information to cover any non-trivial scenarios (like COM) efficiently without effectively forcing a two-level lookup model or hard-coding type support in the `IUnmanagedVirtualMethodTableProvider<T>` implementation. Additionally, we determined that using reflection to get to attributes is considered "okay" and using generic attributes would enable APIs that build on this model like COM to effectively retrieve information from the `System.Type` instance without causing additional problems.
## Example Usage
[assembly:DisableRuntimeMarshalling]
// Define the interface of the native API
-partial interface INativeAPI : IUnmanagedInterfaceType<NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- // There is no concept of casting for this API, but providing a type key is still required by the generator.
- // Use an empty readonly record struct to provide a type that implements IEquatable<T> but contains no data.
- static NoCasting IUnmanagedInterfaceType.TypeKey => default;
[VirtualMethodIndex(0, ImplicitThisParameter = false, Direction = CustomTypeMarshallerDirection.In)]
int GetVersion();
int Multiply(int x, int y);
}
-// Define the key for native "casting" support for our scenario
-readonly record struct NoCasting {}
-
// Define our runtime wrapper type for the native interface.
-unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider<NoCasting>, INativeAPI.Native
+unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native
{
private CNativeAPI* _nativeAPI;
}
}
- VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableInfoForKey(NoCasting _)
+ VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(Type _)
{
return new(IntPtr.Zero, MemoryMarshal.Cast<CNativeAPI, IntPtr>(new ReadOnlySpan<CNativeAPI>(_nativeAPI, 1)));
}
{
int INativeAPI.GetVersion()
{
- var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider<NoCasting>)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
+ var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
int retVal;
retVal = ((delegate* unmanaged<int>)vtable[0])();
return retVal;
{
int INativeAPI.Add(int x, int y)
{
- var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider<NoCasting>)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
+ var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
int retVal;
retVal = ((delegate* unmanaged<int, int, int>)vtable[1])(x, y);
return retVal;
{
int INativeAPI.Multiply(int x, int y)
{
- var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider<NoCasting>)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
+ var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
int retVal;
retVal = ((delegate* unmanaged<int, int, int>)vtable[2])(x, y);
return retVal;
// LibraryImport-generated code omitted for brevity
```
-As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider<T>` with a `T` matching the `TypeKey` type of the native interface.
+As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider`.
The emitted interface implementation can be used in two ways:
using System;
using System.Runtime.InteropServices;
-interface IUnknown: IUnmanagedInterfaceType<Guid>
+interface IUnknown: IUnmanagedInterfaceType<IUnknown>
{
- static Guid IUnmanagedTypeInterfaceType<Guid>.TypeKey => Guid.Parse("00000000-0000-0000-C000-000000000046");
-
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall), typeof(CallConvMemberFunction) })]
[VirtualMethodIndex(0)]
int QueryInterface(in Guid riid, out IntPtr ppvObject);
uint Release();
}
-class BaseIUnknownComObject : IUnmanagedVirtualMethodTableProvider<Guid>, IDynamicInterfaceCastable
+class BaseIUnknownComObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable
{
private IntPtr _unknownPtr;
_unknownPtr = unknown;
}
- unsafe VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider<Guid>.GetVirtualMethodTableInfoForKey(Guid iid)
+ unsafe VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(Type type)
{
- if (iid == IUnknown.TypeKey)
+ if (type == typeof(IUnknown))
{
return new VirtualMethodTableInfo(_unknownPtr, new ReadOnlySpan<IntPtr>(**(IntPtr***)_unknownPtr), 3);
}
{
int IUnknown.QueryInterface(in Guid riid, out IntPtr ppvObject)
{
- var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider<Guid>)this).GetVirtualMethodTableInfoForKey<IUnknown>();
+ var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<IUnknown>();
int retVal;
fixed (Guid* riid__gen_native = &riid)
fixed (IntPtr* ppvObject__gen_native = &ppvObject)
{
uint IUnknown.AddRef()
{
- var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider<Guid>)this).GetVirtualMethodTableInfoForKey<IUnknown>();
+ var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<IUnknown>();
uint retVal;
retVal = ((delegate* unmanaged[Stdcall, MemberFunction]<IntPtr, uint>)vtable[1])(thisPtr);
return retVal;
{
uint IUnknown.Release()
{
- var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider<Guid>)this).GetVirtualMethodTableInfoForKey<IUnknown>();
+ var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<IUnknown>();
uint retVal;
retVal = ((delegate* unmanaged[Stdcall, MemberFunction]<IntPtr, uint>)vtable[2])(thisPtr);
return retVal;
/// <remarks>
/// The generated code assumes it will be in an unsafe context.
/// </remarks>
- public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv, TypeSyntax containingTypeName, ManagedTypeInfo typeKeyType)
+ public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv, TypeSyntax containingTypeName)
{
var setupStatements = new List<StatementSyntax>
{
- // var (<thisParameter>, <virtualMethodTable>) = ((IUnmanagedVirtualMethodTableProvider<<typeKeyType>>)this).GetVirtualMethodTableInfoForKey<<containingTypeName>>();
+ // var (<thisParameter>, <virtualMethodTable>) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<<containingTypeName>>();
ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
SyntaxKind.SimpleMemberAccessExpression,
ParenthesizedExpression(
CastExpression(
- GenericName(
- Identifier(TypeNames.IUnmanagedVirtualMethodTableProvider))
- .WithTypeArgumentList(
- TypeArgumentList(
- SingletonSeparatedList(typeKeyType.Syntax))),
+ ParseTypeName(TypeNames.IUnmanagedVirtualMethodTableProvider),
ThisExpression())),
GenericName(
Identifier("GetVirtualMethodTableInfoForKey"),
namespace Microsoft.Interop
{
- internal sealed record NativeThisInfo(ManagedTypeInfo TypeKeyType) : MarshallingInfo;
+ internal sealed record NativeThisInfo : MarshallingInfo
+ {
+ public static readonly NativeThisInfo Instance = new();
+ }
internal sealed class NativeToManagedThisMarshallerFactory : IMarshallingGeneratorFactory
{
}
public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context)
- => info.MarshallingAttributeInfo is NativeThisInfo(ManagedTypeInfo typeKeyType) ? new Marshaller(typeKeyType) : _inner.Create(info, context);
+ => info.MarshallingAttributeInfo is NativeThisInfo ? new Marshaller() : _inner.Create(info, context);
private sealed class Marshaller : IMarshallingGenerator
{
- private readonly ManagedTypeInfo _typeKeyType;
-
- public Marshaller(ManagedTypeInfo typeKeyType) => _typeKeyType = typeKeyType;
-
public ManagedTypeInfo AsNativeType(TypePositionInfo info) => new PointerTypeInfo("void*", "void*", false);
public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
{
IdentifierName(managedIdentifier),
InvocationExpression(
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- GenericName(Identifier(TypeNames.IUnmanagedVirtualMethodTableProvider),
- TypeArgumentList(
- SingletonSeparatedList(
- _typeKeyType.Syntax))),
+ ParseTypeName(TypeNames.IUnmanagedVirtualMethodTableProvider),
GenericName(Identifier("GetObjectForUnmanagedWrapper"),
TypeArgumentList(
SingletonSeparatedList(
MarshallingInfo ExceptionMarshallingInfo,
MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> ManagedToUnmanagedGeneratorFactory,
MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> UnmanagedToManagedGeneratorFactory,
- ManagedTypeInfo TypeKeyType,
ManagedTypeInfo TypeKeyOwner,
SequenceEqualImmutableArray<Diagnostic> Diagnostics);
ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute);
- var typeKeyOwner = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType);
- ManagedTypeInfo typeKeyType = SpecialTypeInfo.Byte;
+ var interfaceType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType);
- INamedTypeSymbol? iUnmanagedInterfaceTypeInstantiation = symbol.ContainingType.AllInterfaces.FirstOrDefault(iface => SymbolEqualityComparer.Default.Equals(iface.OriginalDefinition, iUnmanagedInterfaceTypeType));
- if (iUnmanagedInterfaceTypeInstantiation is null)
+ INamedTypeSymbol expectedUnmanagedInterfaceType = iUnmanagedInterfaceTypeType.Construct(symbol.ContainingType);
+
+ bool implementsIUnmanagedInterfaceOfSelf = symbol.ContainingType.AllInterfaces.Any(iface => SymbolEqualityComparer.Default.Equals(iface, expectedUnmanagedInterfaceType));
+ if (!implementsIUnmanagedInterfaceOfSelf)
{
// TODO: Report invalid configuration
}
- else
- {
- // The type key is the second generic type parameter, so we need to get the info for the
- // second argument.
- typeKeyType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(iUnmanagedInterfaceTypeInstantiation.TypeArguments[1]);
- }
MarshallingInfo exceptionMarshallingInfo = CreateExceptionMarshallingInfo(virtualMethodIndexAttr, symbol, environment.Compilation, generatorDiagnostics, virtualMethodIndexData);
exceptionMarshallingInfo,
ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.ManagedToUnmanaged),
ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.UnmanagedToManaged),
- typeKeyType,
- typeKeyOwner,
+ interfaceType,
new SequenceEqualImmutableArray<Diagnostic>(generatorDiagnostics.Diagnostics.ToImmutableArray()));
}
BlockSyntax code = stubGenerator.GenerateStubBody(
methodStub.VtableIndexData.Index,
methodStub.CallingConvention.Array,
- methodStub.TypeKeyOwner.Syntax,
- methodStub.TypeKeyType);
+ methodStub.TypeKeyOwner.Syntax);
return (
methodStub.ContainingSyntaxContext.AddContainingSyntax(
var elements = ImmutableArray.CreateBuilder<TypePositionInfo>(originalElements.Length + 2);
- elements.Add(new TypePositionInfo(methodStub.TypeKeyOwner, new NativeThisInfo(methodStub.TypeKeyType))
+ elements.Add(new TypePositionInfo(methodStub.TypeKeyOwner, NativeThisInfo.Instance)
{
InstanceIdentifier = ThisParameterIdentifier,
NativeIndex = 0,
public const string IUnmanagedVirtualMethodTableProvider = "System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider";
- public const string IUnmanagedInterfaceType_Metadata = "System.Runtime.InteropServices.IUnmanagedInterfaceType`2";
+ public const string IUnmanagedInterfaceType_Metadata = "System.Runtime.InteropServices.IUnmanagedInterfaceType`1";
public const string System_Span_Metadata = "System.Span`1";
public const string System_Span = "System.Span";
}
/// <summary>
- /// This interface allows an object to provide information about a virtual method table for a managed interface that implements <see cref="IUnmanagedInterfaceType{TInterface, T}"/> to enable invoking methods in the virtual method table.
+ /// This interface allows an object to provide information about a virtual method table for a managed interface that implements <see cref="IUnmanagedInterfaceType{TInterface}"/> to enable invoking methods in the virtual method table.
/// </summary>
/// <typeparam name="T">The type to use to represent the the identity of the unmanaged type.</typeparam>
- public unsafe interface IUnmanagedVirtualMethodTableProvider<T> where T : IEquatable<T>
+ public unsafe interface IUnmanagedVirtualMethodTableProvider
{
/// <summary>
- /// Get the information about the virtual method table for a given unmanaged interface type represented by <paramref name="typeKey"/>.
+ /// Get the information about the virtual method table for a given unmanaged interface type represented by <paramref name="type"/>.
/// </summary>
- /// <param name="typeKey">The object that represents the identity of the unmanaged interface.</param>
+ /// <param name="type">The managed type for the unmanaged interface.</param>
/// <returns>The virtual method table information for the unmanaged interface.</returns>
- protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey);
+ protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type);
/// <summary>
/// Get the information about the virtual method table for the given unmanaged interface type.
/// <typeparam name="TUnmanagedInterfaceType">The managed interface type that represents the unmanaged interface.</typeparam>
/// <returns>The virtual method table information for the unmanaged interface.</returns>
public sealed VirtualMethodTableInfo GetVirtualMethodTableInfoForKey<TUnmanagedInterfaceType>()
- where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+ where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
- return GetVirtualMethodTableInfoForKey(TUnmanagedInterfaceType.TypeKey);
+ return GetVirtualMethodTableInfoForKey(typeof(TUnmanagedInterfaceType));
}
/// <summary>
/// <typeparam name="TUnmanagedInterfaceType">The managed interface type that represents the unmanaged interface.</typeparam>
/// <returns>The length of the virtual method table for the unmanaged interface.</returns>
public static int GetVirtualMethodTableLength<TUnmanagedInterfaceType>()
- where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+ where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
return TUnmanagedInterfaceType.VirtualMethodTableLength;
}
/// <typeparam name="TUnmanagedInterfaceType">The managed interface type that represents the unmanaged interface.</typeparam>
/// <returns>A pointer to the virtual method table of managed implementations of the unmanaged interface type</returns>
public static void* GetVirtualMethodTableManagedImplementation<TUnmanagedInterfaceType>()
- where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+ where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
return TUnmanagedInterfaceType.VirtualMethodTableManagedImplementation;
}
/// <param name="obj">The managed object that implements the unmanaged interface.</param>
/// <returns>A pointer-sized value that can be passed to unmanaged code that represents <paramref name="obj"/></returns>
public static void* GetUnmanagedWrapperForObject<TUnmanagedInterfaceType>(TUnmanagedInterfaceType obj)
- where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+ where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
return TUnmanagedInterfaceType.GetUnmanagedWrapperForObject(obj);
}
/// <param name="ptr">A pointer-sized value returned by <see cref="GetUnmanagedWrapperForObject{TUnmanagedInterfaceType}(TUnmanagedInterfaceType)"/> or <see cref="IUnmanagedInterfaceType{TInterface, TKey}.GetUnmanagedWrapperForObject(TInterface)"/>.</param>
/// <returns>The object wrapped by <paramref name="ptr"/>.</returns>
public static TUnmanagedInterfaceType GetObjectForUnmanagedWrapper<TUnmanagedInterfaceType>(void* ptr)
- where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+ where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
{
return TUnmanagedInterfaceType.GetObjectForUnmanagedWrapper(ptr);
}
/// </summary>
/// <typeparam name="TInterface">The managed interface.</typeparam>
/// <typeparam name="TKey">The type of a value that can represent types from the corresponding unmanaged type system.</typeparam>
- public unsafe interface IUnmanagedInterfaceType<TInterface, TKey>
- where TInterface : IUnmanagedInterfaceType<TInterface, TKey>
- where TKey : IEquatable<TKey>
+ public unsafe interface IUnmanagedInterfaceType<TInterface>
+ where TInterface : IUnmanagedInterfaceType<TInterface>
{
/// <summary>
/// Get the length of the virtual method table for the given unmanaged interface type.
/// <param name="ptr">A pointer-sized value returned by <see cref="IUnmanagedVirtualMethodTableProvider{TKey}.GetUnmanagedWrapperForObject{IUnmanagedInterfaceType{TInterface, TKey}}(IUnmanagedInterfaceType{TInterface, TKey})"/> or <see cref="GetUnmanagedWrapperForObject(TInterface)"/>.</param>
/// <returns>The object wrapped by <paramref name="ptr"/>.</returns>
public static abstract TInterface GetObjectForUnmanagedWrapper(void* ptr);
-
- /// <summary>
- /// The value that represents the unmanaged type's identity in the corresponding unmanaged type system.
- /// </summary>
- public static abstract TKey TypeKey { get; }
}
}
{
internal partial class ImplicitThis
{
- public readonly record struct NoCasting;
-
- internal partial interface INativeObject : IUnmanagedInterfaceType<INativeObject, NoCasting>
+ internal partial interface INativeObject : IUnmanagedInterfaceType<INativeObject>
{
- static int IUnmanagedInterfaceType<INativeObject, NoCasting>.VirtualMethodTableLength => 2;
+ static int IUnmanagedInterfaceType<INativeObject>.VirtualMethodTableLength => 2;
- static NoCasting IUnmanagedInterfaceType<INativeObject, NoCasting>.TypeKey => default;
- private static void** s_vtable = (void**)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(INativeObject), sizeof(void*) * IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableLength<INativeObject>());
- static void* IUnmanagedInterfaceType<INativeObject, NoCasting>.VirtualMethodTableManagedImplementation
+ private static void** s_vtable = (void**)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(INativeObject), sizeof(void*) * IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<INativeObject>());
+ static void* IUnmanagedInterfaceType<INativeObject>.VirtualMethodTableManagedImplementation
{
get
{
if (s_vtable[0] == null)
{
- Native.PopulateUnmanagedVirtualMethodTable(new Span<IntPtr>(s_vtable, IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableLength<INativeObject>()));
+ Native.PopulateUnmanagedVirtualMethodTable(new Span<IntPtr>(s_vtable, IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<INativeObject>()));
}
return s_vtable;
}
}
- static void* IUnmanagedInterfaceType<INativeObject, NoCasting>.GetUnmanagedWrapperForObject(INativeObject obj)
+ static void* IUnmanagedInterfaceType<INativeObject>.GetUnmanagedWrapperForObject(INativeObject obj)
{
- return VTableGCHandlePair<INativeObject, NoCasting>.Allocate(obj);
+ return VTableGCHandlePair<INativeObject>.Allocate(obj);
}
- static INativeObject IUnmanagedInterfaceType<INativeObject, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr)
+ static INativeObject IUnmanagedInterfaceType<INativeObject>.GetObjectForUnmanagedWrapper(void* ptr)
{
- return VTableGCHandlePair<INativeObject, NoCasting>.GetObject(ptr);
+ return VTableGCHandlePair<INativeObject>.GetObject(ptr);
}
[VirtualMethodIndex(0, ImplicitThisParameter = true)]
}
[NativeMarshalling(typeof(NativeObjectMarshaller))]
- public class NativeObject : INativeObject.Native, IUnmanagedVirtualMethodTableProvider<NoCasting>, IDisposable
+ public class NativeObject : INativeObject.Native, IUnmanagedVirtualMethodTableProvider, IDisposable
{
private readonly void* _pointer;
_pointer = pointer;
}
- public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => new VirtualMethodTableInfo((IntPtr)_pointer, new ReadOnlySpan<IntPtr>(*(void**)_pointer, 2));
+ public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type)
+ {
+ Assert.Equal(typeof(INativeObject), type);
+ return new VirtualMethodTableInfo((IntPtr)_pointer, new ReadOnlySpan<IntPtr>(*(void**)_pointer, 2));
+ }
public void Dispose()
{
ManagedObjectImplementation impl = new ManagedObjectImplementation(startingValue);
- void* wrapper = IUnmanagedVirtualMethodTableProvider<NativeExportsNE.ImplicitThis.NoCasting>.GetUnmanagedWrapperForObject<NativeExportsNE.ImplicitThis.INativeObject>(impl);
+ void* wrapper = IUnmanagedVirtualMethodTableProvider.GetUnmanagedWrapperForObject<NativeExportsNE.ImplicitThis.INativeObject>(impl);
Assert.Equal(startingValue, NativeExportsNE.ImplicitThis.GetNativeObjectData(wrapper));
NativeExportsNE.ImplicitThis.SetNativeObjectData(wrapper, newValue);
// Verify that we actually updated the managed instance.
Assert.Equal(newValue, impl.GetData());
- VTableGCHandlePair<NativeExportsNE.ImplicitThis.INativeObject, NativeExportsNE.ImplicitThis.NoCasting>.Free(wrapper);
+ VTableGCHandlePair<NativeExportsNE.ImplicitThis.INativeObject>.Free(wrapper);
}
class ManagedObjectImplementation : NativeExportsNE.ImplicitThis.INativeObject
{
internal partial class NoImplicitThis
{
- public readonly record struct NoCasting;
-
- internal partial interface IStaticMethodTable : IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>
+ internal partial interface IStaticMethodTable : IUnmanagedInterfaceType<IStaticMethodTable>
{
- static int IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.VirtualMethodTableLength => 2;
- static void* IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.VirtualMethodTableManagedImplementation => null;
-
- static void* IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.GetUnmanagedWrapperForObject(IStaticMethodTable obj) => null;
+ static int IUnmanagedInterfaceType<IStaticMethodTable>.VirtualMethodTableLength => 2;
+ static void* IUnmanagedInterfaceType<IStaticMethodTable>.VirtualMethodTableManagedImplementation => null;
- static IStaticMethodTable IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr) => null;
+ static void* IUnmanagedInterfaceType<IStaticMethodTable>.GetUnmanagedWrapperForObject(IStaticMethodTable obj) => null;
- static NoCasting IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.TypeKey => default;
+ static IStaticMethodTable IUnmanagedInterfaceType<IStaticMethodTable>.GetObjectForUnmanagedWrapper(void* ptr) => null;
[VirtualMethodIndex(0, Direction = MarshalDirection.ManagedToUnmanaged, ImplicitThisParameter = false)]
int Add(int x, int y);
}
[NativeMarshalling(typeof(StaticMethodTableMarshaller))]
- public class StaticMethodTable : IStaticMethodTable.Native, IUnmanagedVirtualMethodTableProvider<NoCasting>
+ public class StaticMethodTable : IStaticMethodTable.Native, IUnmanagedVirtualMethodTableProvider
{
private readonly void* _vtableStart;
_vtableStart = vtableStart;
}
- public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) =>
- new VirtualMethodTableInfo(IntPtr.Zero, new ReadOnlySpan<IntPtr>(_vtableStart, IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableLength<IStaticMethodTable>()));
+ public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type)
+ {
+ Assert.Equal(typeof(IStaticMethodTable), type);
+ return new VirtualMethodTableInfo(IntPtr.Zero, new ReadOnlySpan<IntPtr>(_vtableStart, IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<IStaticMethodTable>()));
+ }
}
[CustomMarshaller(typeof(StaticMethodTable), MarshalMode.ManagedToUnmanagedOut, typeof(StaticMethodTableMarshaller))]
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
namespace ComInterfaceGenerator.Tests
{
- public static unsafe class VTableGCHandlePair<TUnmanagedInterface, TKey>
- where TUnmanagedInterface : IUnmanagedInterfaceType<TUnmanagedInterface, TKey>
- where TKey : IEquatable<TKey>
+ public static unsafe class VTableGCHandlePair<TUnmanagedInterface>
+ where TUnmanagedInterface : IUnmanagedInterfaceType<TUnmanagedInterface>
{
public static void* Allocate(TUnmanagedInterface obj)
{
- void** unmanaged = (void**)NativeMemory.Alloc((nuint)sizeof(void*) * (nuint)IUnmanagedVirtualMethodTableProvider<TKey>.GetVirtualMethodTableLength<TUnmanagedInterface>());
+ void** unmanaged = (void**)NativeMemory.Alloc((nuint)sizeof(void*) * (nuint)IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<TUnmanagedInterface>());
unmanaged[0] = TUnmanagedInterface.VirtualMethodTableManagedImplementation;
unmanaged[1] = (void*)GCHandle.ToIntPtr(GCHandle.Alloc(obj));
return unmanaged;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[VirtualMethodIndex(0)]
void Method();
}
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[SuppressGCTransitionAttribute]
[VirtualMethodIndex(0)]
void Method();
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[UnmanagedCallConv]
[VirtualMethodIndex(0)]
void Method();
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
[VirtualMethodIndex(0)]
void Method();
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })]
[VirtualMethodIndex(0)]
void Method();
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[SuppressGCTransition]
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })]
[VirtualMethodIndex(0)]
{
public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]";
public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;";
- public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl = $$"""
+ public const string INativeAPI_IUnmanagedInterfaceTypeImpl = $$"""
partial interface INativeAPI
{
- {{INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
}
""";
- public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl = """
- static int IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableLength => 1;
- static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableManagedImplementation => null;
- static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
- static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr) => null;
- static NoCasting IUnmanagedInterfaceType<INativeAPI, NoCasting>.TypeKey => default;
+ public const string INativeAPI_IUnmanagedInterfaceTypeMethodImpl = """
+ static int IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableLength => 1;
+ static unsafe void* IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableManagedImplementation => null;
+ static unsafe void* IUnmanagedInterfaceType<INativeAPI>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
+ static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI>.GetObjectForUnmanagedWrapper(void* ptr) => null;
""";
public static string NativeInterfaceUsage() => @"
// Try using the generated native interface
-sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider<NoCasting>, INativeAPI.Native
+sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native
{
- public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null;
+ public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(System.Type type) => throw null;
}
";
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
-readonly record struct NoCasting {}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
[VirtualMethodIndex(0)]
void Method();
-}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static readonly string SpecifiedMethodIndexNoExplicitParametersNoImplicitThis = @"
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
-readonly record struct NoCasting {}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
[VirtualMethodIndex(0, ImplicitThisParameter = false)]
void Method();
-}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static readonly string SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
-readonly record struct NoCasting {}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
[UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
[SuppressGCTransition]
[VirtualMethodIndex(4)]
void Method4();
-}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicParametersAndModifiers(string typeName, string preDeclaration = "") => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0)]
{typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicParametersAndModifiersManagedToUnmanaged(string typeName, string preDeclaration = "") => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, Direction = MarshalDirection.ManagedToUnmanaged)]
{typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicParametersAndModifiers<T>() => BasicParametersAndModifiers(typeof(T).FullName!);
public static string BasicParametersAndModifiersNoRef(string typeName, string preDeclaration = "") => $@"
using System.Runtime.CompilerServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0)]
{typeName} Method({typeName} value, in {typeName} inValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicParametersAndModifiersNoImplicitThis(string typeName) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = false)]
{typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicParametersAndModifiersNoImplicitThis<T>() => BasicParametersAndModifiersNoImplicitThis(typeof(T).FullName!);
public static string MarshalUsingCollectionCountInfoParametersAndModifiers<T>() => MarshalUsingCollectionCountInfoParametersAndModifiers(typeof(T).ToString());
using System.Runtime.InteropServices.Marshalling;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0)]
[return:MarshalUsing(ConstantElementCount=10)]
[MarshalUsing(CountElementName = ""pRefSize"")] ref {collectionType} pRef,
[MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut,
out int pOutSize);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicReturnTypeComExceptionHandling(string typeName, string preDeclaration = "") => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.Marshalling;
{preDeclaration}
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ExceptionMarshalling = ExceptionMarshalling.Com)]
{typeName} Method();
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public static string BasicReturnTypeCustomExceptionHandling(string typeName, string customExceptionType, string preDeclaration = "") => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.Marshalling;
{preDeclaration}
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, CustomExceptionMarshallingType = typeof({customExceptionType}))]
{typeName} Method();
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
public class ManagedToUnmanaged : IVirtualMethodIndexSignatureProvider<ManagedToUnmanaged>
{
public static bool ImplicitThisParameter => true;
// Unmanaged-to-managed-only stubs don't provide implementations for the interface, so we don't want to try to use the generated nested interface
- // since it won't have managed implementations for the meth
+ // since it won't have managed implementations for the methods
public static string NativeInterfaceUsage() => string.Empty;
}
public class Bidirectional : IVirtualMethodIndexSignatureProvider<Bidirectional>
public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]";
public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;";
- public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl = $$"""
+ public const string INativeAPI_IUnmanagedInterfaceTypeImpl = $$"""
partial interface INativeAPI
{
- {{INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
}
""";
- public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl = """
- static int IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableLength => 1;
- static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableManagedImplementation => null;
- static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
- static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr) => null;
- static NoCasting IUnmanagedInterfaceType<INativeAPI, NoCasting>.TypeKey => default;
+ public const string INativeAPI_IUnmanagedInterfaceTypeMethodImpl = """
+ static int IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableLength => 1;
+ static unsafe void* IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableManagedImplementation => null;
+ static unsafe void* IUnmanagedInterfaceType<INativeAPI>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
+ static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI>.GetObjectForUnmanagedWrapper(void* ptr) => null;
""";
public static abstract string NativeInterfaceUsage();
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
{typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.BasicParametersAndModifiersNoRef(string typeName, string preDeclaration) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
{typeName} Method({typeName} value, in {typeName} inValue, out {typeName} outValue);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.BasicParameterByValue(string typeName, string preDeclaration) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.Marshalling;
{preDeclaration}
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
void Method({typeName} value);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.BasicParameterWithByRefModifier(string modifier, string typeName, string preDeclaration) => $@"
using System.Runtime.CompilerServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
void Method({modifier} {typeName} value);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.BasicReturnType(string typeName, string preDeclaration) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
{preDeclaration}
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
{typeName} Method();
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.MarshalUsingParametersAndModifiers(string typeName, string marshallerTypeName, string preDeclaration) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
{preDeclaration}
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
[return: MarshalUsing(typeof({marshallerTypeName}))]
[MarshalUsing(typeof({marshallerTypeName}))] in {typeName} pIn,
[MarshalUsing(typeof({marshallerTypeName}))] ref {typeName} pRef,
[MarshalUsing(typeof({marshallerTypeName}))] out {typeName} pOut);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
[return:MarshalUsing(ConstantElementCount=10)]
[MarshalUsing(CountElementName = ""pRefSize"")] ref {collectionType} pRef,
[MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut,
out int pOutSize);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionParametersAndModifiers(string collectionType, string marshallerType) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
[return:MarshalUsing(typeof({marshallerType}), ConstantElementCount=10)]
[MarshalUsing(typeof({marshallerType}), CountElementName = ""pOutSize"")] out {collectionType} pOut,
out int pOutSize
);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionReturnValueLength(string collectionType, string marshallerType) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
int Method(
[MarshalUsing(typeof({marshallerType}), CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out {collectionType} pOut
);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionOutConstantLength(string collectionType, string predeclaration) => $@"
using System.Runtime.CompilerServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
int Method(
[MarshalUsing(ConstantElementCount = 10)] out {collectionType} pOut
);
}}
-" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionReturnConstantLength(string collectionType, string predeclaration) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
[return:MarshalUsing(ConstantElementCount = 10)]
{collectionType} Method();
}}
-" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
static string ICustomMarshallingSignatureTestProvider.CustomElementMarshalling(string collectionType, string elementMarshaller, string predeclaration) => $@"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{{
[VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
[return:MarshalUsing(ConstantElementCount=10)]
out int pOutSize
);
}}
-" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
}
}
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[VirtualMethodIndex(0)]
void Method();
}
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[VirtualMethodIndex(0)]
void Method();
}
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[VirtualMethodIndex(0)]
void Method();
}
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
- readonly record struct NoCasting {}
- partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
{
- {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+ {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
[VirtualMethodIndex(0)]
void Method();
}