我有一个原生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提供更多的报道以确保。同时,如果有人知道什么可能导致这种例外,以及如何防止这种情况,我真的很感激答案。
答案 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属性也无法编组委托。但是无法使用本机库对其进行测试。