我正在使用extern
DLL,它有一堆返回ReturnCode
枚举的例程,因此我编写了以下帮助函数来记录所有错误:
let mutable LastError = ReturnCode.OK
let mutable LastReturnCode = ReturnCode.OK
let mutable TotalErrors = 0
let Run (call: unit -> ReturnCode) =
LastReturnCode <- call()
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
很好,除了一些DLL的函数有out
个参数。所以现在我做的事情就像
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &evfImageHandle))
evfImageHandle
编译器给我一个“可变变量无法通过闭包捕获”的错误。除了在任何地方内联Run
之外,我还能做些什么吗?这在C#中运行良好。
(以下示例extern声明)
[<DllImport(EDSDKPath)>]
extern ReturnCode EdsCreateEvfImageRef(int inStreamHandle, [<Out>] int& outEvfImageHandle);
答案 0 :(得分:6)
您仍然可以使用ref
类型,但在传递对函数的引用时不需要编写&
符号 - 编译器将自动执行此操作:
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, evfImageHandle))
!evfImageHandle
答案 1 :(得分:3)
标准解决方案是使用引用 - 代码变为
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &(!evfImageHandle)))
!evfImageHandle
然而,这不起作用,因为编译器要求!evfImageHandle
是可变的,而不是。
我认为这里真正的解决方案是更改你的Run
函数,使其不需要关闭,而只需要返回值 - 这至少会使它在这种情况下起作用。然后代码变成
let Run (call: ReturnCode) =
LastReturnCode <- call
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
并且代码更改为
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = 0
Extern.EdsCreateEvfImageRef (streamHandle, &evfImageHandle)) |> Run
evfImageHandle
或更恶意的解决方案。使用数组成员可变的事实,并且可以通过闭包来捕获
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = [|0|]
Run (fun () -> EdsCreateEvfImageRef (streamHandle, &(evfImageHandle.[0])) )
evfImageHandle.[0]