在 F# 中使用 SafeHandles
Posted
技术标签:
【中文标题】在 F# 中使用 SafeHandles【英文标题】:Working with SafeHandles in F# 【发布时间】:2014-07-28 21:02:56 【问题描述】:我正在处理一些使用平台调用的 F# 代码。我正在使用的 API 之一返回一个句柄。我没有使用nativeint
,而是实现了我自己的SafeHandle(特别是SafeHandleMinusOneIsInvalid
。)这使得使用包含pinvoke 签名的模块有点笨拙。这是一个例子:
type MySafeHandle() =
inherit SafeHandleZeroOrMinusOneIsInvalid(true)
override this.ReleaseHandle() =
NativeMethods.FreeHandle(base.handle)
true
module NativeMethods =
[<DllImport("mylibrary.dll")>]
extern void GetHandle([<Out>]MySafeHandle& handle)
[<DllImport("mylibrary.dll")>]
extern void FreeHandle(nativeint handle)
这不会编译,因为模块和类递归地相互引用,这是行不通的。如果我将模块移到MySafeHandle
上方,那么GetHandle
将看不到SafeHandle。
我无法在 MySafeHandle
中移动平台调用方法,因为 F# must be in modules 中的 extern 方法似乎存在(即使编译器不会阻止您尝试将它们放入类中)。
F# 的 recursive types 似乎也不能在模块和类之间工作,只能在类之间工作。
是否有不需要声明两个不同模块的解决方案来解决这个问题?理想情况下,我希望将所有平台调用代码组织到一个模块中。
【问题讨论】:
两个模块确实是最干净的解决方案。 【参考方案1】:我知道一个,因为我自己也有同样的问题。
问题是,我猜它有点丑:
它涉及到您稍后在模块中设置为导入函数的静态引用。
type MySafeHandle() =
inherit SafeHandleZeroOrMinusOneIsInvalid(true)
static let freeHandle = ref Unchecked.defaultof<_>
static member internal SetFreeHandleRef value = freeHandle := value
override this.ReleaseHandle() =
!freeHandle base.handle
true
module NativeMethods =
[<DllImport("mylibrary.dll")>]
extern void GetHandle([<Out>]MySafeHandle& handle)
[<DllImport("mylibrary.dll")>]
extern void FreeHandle(nativeint handle)
MySafeHandle.SetFreeHandleRef FreeHandle
【讨论】:
以上是关于在 F# 中使用 SafeHandles的主要内容,如果未能解决你的问题,请参考以下文章