Работа с SafeHandles в F#

Я работаю с некоторым кодом F#, который использует вызов платформы. Один из используемых мной API возвращает дескриптор. Вместо использования nativeint Я реализовал свой собственный SafeHandle (в частности, SafeHandleMinusOneIsInvalid.) Это делает работу с модулем, содержащим подпись pinvoke, немного неуклюжей. Вот пример:

type MySafeHandle() = 
    inherit SafeHandleZeroOrMinusOneIsInvalid(true)

    override this.ReleaseHandle() =
        NativeMethods.FreeHandle(base.handle)            
        true

module NativeMethods = 
    [<DllImport("mylibrary.dll")>]
    extern void GetHandle([<Out>]MySafeHandle& handle)
    [<DllImport("mylibrary.dll")>]
    extern void FreeHandle(nativeint handle)

Это не скомпилируется, потому что модуль и класс рекурсивно ссылаются друг на друга, что не работает. Если я переместить модуль выше MySafeHandle, затем GetHandle не увидит SafeHandle.

Я не могу переместить платформу вызывать методы внутри MySafeHandle поскольку кажется, что методы extern в F# должны быть в модулях (даже если компилятор не остановит вас от попыток поместить их в класс).

Также кажется, что рекурсивные типы F# не работают между модулем и классом, только классы.

Есть ли решение этой проблемы, которое не требует объявления двух разных модулей? В идеале я хотел бы, чтобы весь код вызова моей платформы был организован в одном модуле.

1 ответ

Ну, я знаю об одном, потому что у меня была такая же проблема.

Дело в том, что это довольно уродливо, я думаю:

Он включает в себя статическую ссылку, которую вы установите для импортируемой функции позже в модуле.

type MySafeHandle() = 
    inherit SafeHandleZeroOrMinusOneIsInvalid(true)
    static let freeHandle = ref Unchecked.defaultof<_>
    static member internal SetFreeHandleRef value = freeHandle := value

    override this.ReleaseHandle() =
        !freeHandle base.handle            
        true

module NativeMethods = 
    [<DllImport("mylibrary.dll")>]
    extern void GetHandle([<Out>]MySafeHandle& handle)
    [<DllImport("mylibrary.dll")>]
    extern void FreeHandle(nativeint handle)

    MySafeHandle.SetFreeHandleRef FreeHandle
Другие вопросы по тегам