我正在处理一些使用平台调用的 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 中似乎有外部方法(即使编译器不会阻止您尝试将它们放入类中)。
似乎 F# 的 recursive types不要在模块和类之间工作,只能在类之间工作。
是否有不需要声明两个不同模块的解决方案?理想情况下,我希望将所有平台调用代码组织到一个模块中。
最佳答案
嗯,我知道一个,因为我自己也遇到过同样的问题。
问题是,我猜它有点丑:
它涉及您稍后在模块中设置为导入函数的静态引用。
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# - 在 F# 中使用安全句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25004314/