F#Marshall使用委托类型字段进行结构化

时间:2015-08-28 09:31:19

标签: f# f#-interactive

我有一个原生C库,我想用它做一些F#编码。事情是我得到例外:

  

System.TypeLoadException:无法编组字段' log'类型   ' LoggingModel':此类型没有编组支持。
  在   System.StubHelpers.ValueClassMarshaler.ConvertToNative(IntPtr dst,   IntPtr src,IntPtr pMT,CleanupWorkList& pCleanupWorkList)
  在   FSI_0009.Initialize(ComponentOverrideFlags标志,LoggingModel&   loggingModel,ThreadingModel& threadingModel,SchedulingModel&   schedulingModel,IntPtr memoryModel)
  在   。$ @ FSI_0011.main()   在   D:\ dev_p \ f#\ FunBindings \ FunExample \ Environment.fs:第16行停止到期   错误

这里是代码:

module Interop

[<CLSCompliant(true); Flags>]
type LogTarget =
    | None = 0
    | Console = 1
    | Trace = 2
    | Custom = 4 

[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
type LogCallback = delegate of LogTarget * string * string * nativeint -> unit

[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>]
type ReleaseCallback = delegate of nativeint -> unit

[<Struct>]
type LoggingModel =
    val mutable targets : LogTarget
    val mutable log : LogCallback
    val mutable deleteModel : ReleaseCallback
    val mutable userparam : IntPtr

[<DllImport("CLIBRARY.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "txInitialize")>]
[<MethodImpl(MethodImplOptions.ForwardRef)>]
extern int Initialize(ComponentOverrideFlags flags, LoggingModel& loggingModel, ThreadingModel& threadingModel, SchedulingModel& schedulingModel, IntPtr memoryModel)

module Environment

let initialize =
    let mutable loggingModel = new LoggingModel()
    let mutable threadingModel = new ThreadingModel()
    let mutable schedulingModel = new SchedulingModel()
    Initialize(ComponentOverrideFlags.None, &loggingModel, &threadingModel, &schedulingModel, IntPtr.Zero)

基本上,当我尝试执行&#34;初始化&#34;时,我得到了上述错误。交互式功能。

我真的很感激任何帮助。

更新:我已经检查了一些代码,并注意到在交互式控制台之外它似乎正在工作,没有异常。我需要为CLibrary提供更多的报道以确保。同时,如果有人知道什么可能导致这种例外,以及如何防止这种情况,我真的很感激答案。

2 个答案:

答案 0 :(得分:2)

我认为问题是delegate of LogTarget * string * string * nativeint -> unit声明一个委托,其中参数是curried。 (这对我来说没有任何意义,因为a * b通常代表一个元组。)

微妙的不同delegate of (LogTarget * string * string * nativeint) -> unit声明一个带有tupled参数的委托,它与本机函数兼容。

如果尝试将.NET方法分配给两种不同的委托类型,则可以看到这种差异:

type Curried = delegate of int * int -> int
type Tupled = delegate of (int * int) -> int

//let a = new Curried (Math.Max) // doesn't compile
let b = new Tupled (Math.Max) // works

答案 1 :(得分:0)

您是否尝试将[<MarshalAsAttribute(UnmanagedType.FunctionPtr)>]添加到LoggingModel?

[<Struct>]
type LoggingModel =
    val mutable targets : LogTarget
    [<MarshalAsAttribute(UnmanagedType.FunctionPtr)>]
    val mutable log : LogCallback
    [<MarshalAsAttribute(UnmanagedType.FunctionPtr)>]
    val mutable deleteModel : ReleaseCallback
    val mutable userparam : IntPtr

没有此属性的IL代码是:

// Fields
.field public class Interop.LogCallback log

但是这个属性是:

// Fields
.field public marshal(Func) class Interop.LogCallback log

如果没有marshal(Func) / MarshalAs属性,即使使用UnmanagedFunctionPointer属性也无法编组委托。但是无法使用本机库对其进行测试。