2015-08-28 15 views
6

Yerel bir C kitaplığım var ve onunla bazı F # kodlaması yapmak istiyorum. şey istisna olsun:F # Delege türü alanına sahip Marshall yapıları

System.TypeLoadException: mareşal alan türü 'LoggingModel' arasında 'log' Can not: bu tip hiçbir dizme desteği yoktur. System.StubHelpers.ValueClassMarshaler.ConvertToNative de
(IntPtr DST, ıntptr src, ıntptr pMT, CleanupWorkList & pCleanupWorkList) FSI_0009.Initialize (ComponentOverrideFlags bayrakları olarak
, LoggingModel & loggingModel, ThreadingModel & ThreadingModel'ı, SchedulingModel & schedulingModel, ıntptr memoryModel) de
$ FSI_0011.main @() D içinde:. \ dev_p \ f \ # FunBindings \ FunExample Environment.fs \: satır 16nedeniyle durduruldu Ben interaktif işlevi yürütmek "başlatmak" çalıştığınızda

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) 

Temelde, yukarıda belirtilen hata alıyorum:İşte kodu

hata.

Gerçekten herhangi bir yardım için minnettar olurum.

Güncelleme: Kodu biraz daha kontrol ettim ve etkileşimli konsolun dışında, istisnalarla karşılaşmadan çalıştığı görülüyor. Emin olmak için CLibrary için biraz daha fazla bilgi vermem gerekiyor. Bu arada, bu istisnaya neyin yol açabileceğini bilen ve nasıl önlenebileceğini bilen varsa, cevabı gerçekten takdir ediyorum.

cevap

2

Sorun, delegate of LogTarget * string * string * nativeint -> unit'un argümanların körlendiği bir delege olduğunu bildirmesidir. (Bu, a * b normalde bir tuple temsil ettiğinden, bu bana gerçekten mantıklı gelmiyor.)

Son derece farklı olan delegate of (LogTarget * string * string * nativeint) -> unit, yerel bir işlevle uyumlu olacak şekilde tupled argümanları olan bir temsilci bildirir.

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 
+0

Üzgünüz, Tim, yardımcı olmadı. Tam istisna bilgisi ile soru düzenleyeceğim. – PompolutZ

0

sen LoggingModel için [<MarshalAsAttribute(UnmanagedType.FunctionPtr)>] ekleyerek denediniz: Eğer denemek ve iki farklı temsilci türlerine bir .NET yöntemini atarsanız

Bu farkı görebilirsiniz?

// Fields 
.field public class Interop.LogCallback log 

ancak bu özellik ile olduğu:: Bu özellik olmadan

[<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 kodu

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

marshal(Func) olmadan/MarshalAs temsilci da UnmanagedFunctionPointer öznitelik ile sıraya edilemez bağlamaktadır. Ancak yerel bir kütüphaneyle test edilemez.

+0

Evet, bunu daha önce denedim. Ne yazık ki, yardımcı olmuyor. Aynı hata. – PompolutZ

+0

Ayrıca, türünde LogCallback = (LogTarget * string * string * nativeint) -> unit 'türünde argüman işlevlerini çalıştırmak için ilgili MarshalAs'ı eklemeyi denediniz. '] Hedef: LogTarget'? Muhtemelen enum varsayılan marshalling yok. –

+0

Merhaba, sadece denedim ve aynı kalır. İstisna hala günlük alanında işaret ediyor. – PompolutZ