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 DynamicallyAccessedMembers attribute to CreateSafeHandle API #373

Merged
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
@@ -1,7 +1,14 @@

namespace System.Runtime.InteropServices
{
// [TODO] Remove once the attribute has been added to the BCL
/// <summary>
/// Indicates that method will be generated at compile time and invoke into an unmanaged library entry point
/// </summary>
/// <remarks>
/// IL linker/trimming currently has special handling of P/Invokes (pinvokeimpl):
/// - https://github.com/mono/linker/blob/bfab847356063d21eb15e79f2b6c03df5bd6ef3d/src/linker/Linker.Steps/MarkStep.cs#L2623
/// We may want to make the linker aware of this attribute as well.
/// </remarks>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class GeneratedDllImportAttribute : Attribute
{
Expand Down
16 changes: 15 additions & 1 deletion DllImportGenerator/Ancillary.Interop/MarshalEx.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace System.Runtime.InteropServices
Expand All @@ -9,7 +10,15 @@ namespace System.Runtime.InteropServices
/// </summary>
public static class MarshalEx
{
public static TSafeHandle CreateSafeHandle<TSafeHandle>()
/// <summary>
/// Create an instance of the given <typeparamref name="TSafeHandle"/>.
/// </summary>
/// <typeparam name="TSafeHandle">Type of the SafeHandle</typeparam>
/// <returns>New instance of <typeparamref name="TSafeHandle"/></returns>
/// <remarks>
/// The <typeparamref name="TSafeHandle"/> must be non-abstract and have a parameterless constructor.
/// </remarks>
public static TSafeHandle CreateSafeHandle<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicConstructors)]TSafeHandle>()
where TSafeHandle : SafeHandle
{
if (typeof(TSafeHandle).IsAbstract || typeof(TSafeHandle).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, null, Type.EmptyTypes, null) == null)
Expand All @@ -21,6 +30,11 @@ public static TSafeHandle CreateSafeHandle<TSafeHandle>()
return safeHandle;
}

/// <summary>
/// Sets the handle of <paramref name="safeHandle"/> to the specified <paramref name="handle"/>.
/// </summary>
/// <param name="safeHandle"><see cref="SafeHandle"/> instance to update</param>
/// <param name="handle">Pre-existing handle</param>
public static void SetHandle(SafeHandle safeHandle, IntPtr handle)
{
typeof(SafeHandle).GetMethod("SetHandle", BindingFlags.NonPublic | BindingFlags.Instance)!.Invoke(safeHandle, new object[] { handle });
Expand Down