未验证 提交 cdd75667 编写于 作者: J Jeremy Koritzinsky 提交者: GitHub

Specially consider CLong, CULong and Guid strictly blittable (#88213)

上级 2f208128
......@@ -14,6 +14,23 @@ Support for `MarshalAs(UnmanagedType.Interface)` is added to the interop source
The `ComInterfaceMarshaller<T>` type has the following general behavior: An unmanaged pointer is marshalled to a managed object through `GetOrCreateObjectForComInstance` on a shared `StrategyBasedComWrappers` instance. A managed object is marshalled to an unmanaged pointer through that same shared instance with the `GetOrCreateComInterfaceForObject` method and then calling `QueryInterface` on the returned `IUnknown*` to get the pointer for the unmanaged interface with the IID from the managed type as defined by our default interface details strategy (or the IID of `IUnknown` if the managed type has no IID).
### Strict Blittability
Strict blittability checks have been slightly relaxed. A few select types are now considered strictly blittable that previously were not:
- `System.Runtime.InteropServices.CLong`
- `System.Runtime.InteropServices.CULong`
- `System.Guid`
The first two types are interop intrinsics that were specifically designed to be used at the unmanaged API layer, so they should be considered blittable by all interop systems. `System.Guid` is extremely commonly used in COM-based APIs, and with the move to supporting COM interop in source-generation, this type shows up in signatures quite a bit. As .NET has always maintained that `Guid` is a blittable representation of `GUID` and it is marked as `NonVersionable` (so we have already committed to maintain the shape between multiple versions of the runtime), we have decided to add it to the list of strictly blittable types.
We strive to keep this list of "exceptions" to our strict blittability rules small, but we will continue to evaluate the list of types in the future as we explore new interop scenarios. We will follow these rules to determine if we will consider encoding the type as strictly blittable in the future:
- The type is defined in the same assembly as `System.Object` (the core assembly) and is marked either as `NonVersionable` or `Intrinsic` in CoreCLR's System.Private.CoreLib.
- The type is an primitive ABI type defined by the interop team.
Types that meet one of these two criterion will have stable shapes and will not accidentally introduce non-blittable fields like `bool` and `char`, so we can consider adding them to the exception list. We do not guarantee that we will add any more types as exceptions in the future, but we will consider it if we find a compelling reason to do so.
## Version 2 (.NET 7 Release)
The focus of version 2 is to support all repos that make up the .NET Product, including ASP.NET Core and Windows Forms, as well as all packages in dotnet/runtime.
......
......@@ -156,5 +156,9 @@ public static string MarshalEx(InteropGenerationOptions options)
public const string System_Runtime_InteropServices_Marshalling_ComObject = "System.Runtime.InteropServices.Marshalling.ComObject";
public const string System_Runtime_InteropServices_BestFitMappingAttribute = "System.Runtime.InteropServices.BestFitMappingAttribute";
public const string System_Runtime_InteropServices_CLong = "System.Runtime.InteropServices.CLong";
public const string System_Runtime_InteropServices_CULong = "System.Runtime.InteropServices.CULong";
}
}
......@@ -72,6 +72,20 @@ static unsafe bool IsStrictlyBlittableWorker(ITypeSymbol t, ImmutableHashSet<ITy
if (t.ContainingAssembly is not ISourceAssemblySymbol sourceAssembly
|| sourceAssembly.Compilation != compilation)
{
// We have a few exceptions to this rule. We allow a select number of types that we know are unmanaged and will always be unmanaged.
if (t.ToDisplayString() is TypeNames.System_Runtime_InteropServices_CLong // CLong is an interop intrinsic type for the C long type
or TypeNames.System_Runtime_InteropServices_CULong)// CULong is an interop intrinsic type for the C ulong type
{
return true;
}
if (t.ContainingAssembly.Equals(compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly, SymbolEqualityComparer.Default))
{
if (t.ToDisplayString() == TypeNames.System_Guid) // .NET has established that Guid is blittable and matches the shape of the Win32 GUID type exactly and always will.
{
return true;
}
}
return false;
}
......
......@@ -33,30 +33,35 @@ public class Compiles
public static IEnumerable<object[]> CodeSnippetsToCompile()
{
yield return new[] { ID(), CodeSnippets.TrivialClassDeclarations };
yield return new[] { ID(), CodeSnippets.TrivialStructDeclarations };
yield return new[] { ID(), CodeSnippets.MultipleAttributes };
yield return new[] { ID(), CodeSnippets.NestedNamespace };
yield return new[] { ID(), CodeSnippets.NestedTypes };
yield return new[] { ID(), CodeSnippets.UnsafeContext };
yield return new[] { ID(), CodeSnippets.UserDefinedEntryPoint };
yield return new[] { ID(), CodeSnippets.AllLibraryImportNamedArguments };
yield return new[] { ID(), CodeSnippets.DefaultParameters };
yield return new[] { ID(), CodeSnippets.UseCSharpFeaturesForConstants };
// Parameter / return types
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<byte>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<sbyte>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<short>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<ushort>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<int>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<uint>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<long>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<ulong>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<float>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<double>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<IntPtr>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<UIntPtr>() };
//yield return new[] { ID(), CodeSnippets.TrivialClassDeclarations };
//yield return new[] { ID(), CodeSnippets.TrivialStructDeclarations };
//yield return new[] { ID(), CodeSnippets.MultipleAttributes };
//yield return new[] { ID(), CodeSnippets.NestedNamespace };
//yield return new[] { ID(), CodeSnippets.NestedTypes };
//yield return new[] { ID(), CodeSnippets.UnsafeContext };
//yield return new[] { ID(), CodeSnippets.UserDefinedEntryPoint };
//yield return new[] { ID(), CodeSnippets.AllLibraryImportNamedArguments };
//yield return new[] { ID(), CodeSnippets.DefaultParameters };
//yield return new[] { ID(), CodeSnippets.UseCSharpFeaturesForConstants };
//// Parameter / return types
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<byte>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<sbyte>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<short>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<ushort>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<int>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<uint>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<long>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<ulong>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<float>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<double>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<IntPtr>() };
//yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<UIntPtr>() };
// Parameter / return types for specially considered "strictly blittable" types.
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<CLong>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<CULong>() };
yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers<Guid>() };
// Arrays
yield return new[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<byte>() };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册