为了异步错误处理,我需要向Cuda流添加回调。我有一个看起来像这样的函数,需要在Spiral中进行重写,并将其编译为F#。
type unit_to_unit_delegate = delegate of unit -> unit
let add_callback_to_stream (str : CudaStream) (callback : unit -> unit) =
let callb (str : CUstream) (res : CUResult) (p : nativeint) =
let t : unit_to_unit_delegate = Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(p)
t.Invoke()
let aux = new unit_to_unit_delegate (callback)
let ptr_to_aux = Marshal.GetFunctionPointerForDelegate aux
let cuda_callback = CUstreamCallback(callb)
str.AddCallback(cuda_callback,ptr_to_aux,CUStreamAddCallbackFlags.None)
第一行是给我麻烦的那一行。我没有办法像在F#中那样在Spiral中明确声明委托类型。我通常使用宏进行互操作,但是在这里我无法使用它们。
如果未在某个地方的库中定义它,我可能需要修改代码生成器,以在编译开始时打印出type unit_to_unit_delegate = delegate of unit -> unit
。
答案 0 :(得分:2)
有一系列通用的.NET委托System.Action
和System.Func
可以满足您的需求。这些由.NET定义,因此它们使用void
而不是unit
。根据您的用例,可能会很好,但是如果您做的比较棘手,则可能会遇到问题。给定类型为callback
的F#函数unit -> unit
,您可以使用:
System.Action
是一个没有参数返回void的委托。 F#可以使用callback
new System.Action(callback)
转换为此委托人
System.Action<T>
是一个委托,它接受一个类型为T
的参数并返回void
。 F#也可以将callback
转换为这种类型:new System.Action<unit>(callback)
System.Func<T, R>
是一个接受T
并返回R
的委托。同样,您可以使用
new System.Func<unit, unit>(callback)
获得一个Func<unit, unit>
值
我将从第一个开始,除非您明确需要将委托编译为.NET代码并返回Microsoft.FSharp.Core.Unit
的委托。