【发布时间】:2018-09-05 20:09:31
【问题描述】:
也许是一个愚蠢的问题...我是 C# 和 .Net 的新手。
In the example for the SafeHandle class (C#) on MSDN,代码让我有点摸不着头脑。
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal class MySafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private MySafeFileHandle()
: base(true)
{}
// other code here
}
[SuppressUnmanagedCodeSecurity()]
internal static class NativeMethods
{
// other code...
// Allocate a file object in the kernel, then return a handle to it.
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
internal extern static MySafeFileHandle CreateFile(String fileName,
int dwDesiredAccess, System.IO.FileShare dwShareMode,
IntPtr securityAttrs_MustBeZero, System.IO.FileMode
dwCreationDisposition, int dwFlagsAndAttributes,
IntPtr hTemplateFile_MustBeZero);
// other code...
}
// Later in the code the handle is created like this:
MySafeFileHandle tmpHandle;
tmpHandle = NativeMethods.CreateFile(fileName, NativeMethods.GENERIC_READ,
FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
我的问题是: C 函数 CreateFile 中的 Win32 HANDLE 如何进入受保护的 MySafeFileHandle 对象 IntPtr "handle" 变量? MySafeFileHandle 的构造函数是私有的,甚至不接受 IntPtr 作为参数!
CreateFile 声明上方的评论说了一些关于
…CLR 的平台编组层将以原子方式将句柄存储到 SafeHandle 对象中。
我不确定我确切地知道这意味着什么,谁能解释一下吗?
【问题讨论】:
-
基本上,这很神奇。运行时“知道”
SafeHandle以及如何将IntPtrs 填充到其中。当然,运行时不受构造函数规则的约束。 -
同样,C# 编译器可以创建不合法的 C# 代码。仅仅因为你必须遵守规则并不意味着其他人必须这样做。
-
CreateFile() 不返回安全句柄。它是一个纯粹的非托管函数,不知道有关 .NET 对象的 bean。但是 [DllImport] 声明说确实如此。现在是 pinvoke marshaller 的工作,即 CLR 中进行本机函数调用的代码块,将 IntPtr 转换为 MySafeFileHandle 对象。它知道很多转换技巧,这只是其中之一。
-
顺便说一句,这根本不是一个愚蠢的问题。围绕某些非托管对象的互操作是基本运行时 imo 中最复杂的东西。一些使已知句柄类型以直观方式表现的终结器技巧变得……讨厌。幸运的是,这只会在处理 CLR不 知道的句柄类型时成为典型用户的问题。 (例如自定义硬件中真正有限资源的句柄)