Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for abstract SafeHandle types for by-value marshalling. #1066

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -843,6 +843,15 @@ public static partial void Method(
{byRefKind} {typeName} p);
}}";

public static string BasicParameterByValue(string typeName) => @$"
using System.Runtime.InteropServices;
partial class Test
{{
[GeneratedDllImport(""DoesNotExist"")]
public static partial void Method(
{typeName} p);
}}";

public static string BasicReturnType(string typeName) => @$"
using System.Runtime.InteropServices;
partial class Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ public static IEnumerable<object[]> CodeSnippetsToCompile()

// Custom type marshalling in arrays (complex case with Value property)
yield return new object[] { CodeSnippets.ArrayMarshallingWithCustomStructElementWithValueProperty, 5, 0 };

// Abstract SafeHandle type by reference
yield return new object[] { CodeSnippets.BasicParameterWithByRefModifier("ref", "System.Runtime.InteropServices.SafeHandle"), 1, 0 };
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ public static IEnumerable<object[]> CodeSnippetsToCompile()

// SafeHandle
yield return new[] { CodeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle") };
yield return new[] { CodeSnippets.BasicParameterByValue("System.Runtime.InteropServices.SafeHandle") };
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
yield return new[] { CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: false) };
yield return new[] { CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: true) };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ private static IMarshallingGenerator CreateCore(
{
throw new MarshallingNotSupportedException(info, context);
}
if (info.IsByRef && info.ManagedType.IsAbstract)
{
throw new MarshallingNotSupportedException(info, context)
{
NotSupportedDetails = Resources.SafeHandleByRefMustBeConcrete
};
}
return new SafeHandleMarshaller(options);

// Marshalling in new model.
Expand Down
9 changes: 9 additions & 0 deletions DllImportGenerator/DllImportGenerator/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions DllImportGenerator/DllImportGenerator/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@
<data name="RefValuePropertyUnsupportedMessage" xml:space="preserve">
<value>The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property.</value>
</data>
<data name="SafeHandleByRefMustBeConcrete" xml:space="preserve">
<value>An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete.</value>
</data>
<data name="StackallocConstructorMustHaveStackBufferSizeConstantDescription" xml:space="preserve">
<value>When constructor taking a Span&lt;byte&gt; is specified on the native type, the type must also have a public integer constant named StackBufferSize to provide the size of the stack-allocated buffer.</value>
</data>
Expand Down
5 changes: 2 additions & 3 deletions DllImportGenerator/DllImportGenerator/TypePositionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,10 @@ static bool TryCreateTypeBasedMarshallingInfo(ITypeSymbol type, DefaultMarshalli
var conversion = compilation.ClassifyCommonConversion(type, compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_SafeHandle)!);
if (conversion.Exists
&& conversion.IsImplicit
&& conversion.IsReference
&& !type.IsAbstract)
&& (conversion.IsReference || conversion.IsIdentity))
{
bool hasAccessibleDefaultConstructor = false;
if (type is INamedTypeSymbol named && named.InstanceConstructors.Length > 0)
if (type is INamedTypeSymbol named && !named.IsAbstract && named.InstanceConstructors.Length > 0)
{
foreach (var ctor in named.InstanceConstructors)
{
Expand Down