Working with SafeHandles in F# - f#

I'm working with some F# code that uses platform invoke. One of the APIs I'm using returns a handle. Instead of using a nativeint, I've implemented my own SafeHandle (specifically SafeHandleMinusOneIsInvalid.) This makes working with the module containing the pinvoke signature a little clunky. Here is an example:
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)
This won't compile because the module and the class recursively reference each other, which doesn't work. If I move the module above MySafeHandle, then GetHandle won't see the SafeHandle.
I can't move the platform invoke methods inside of MySafeHandle since it appears that extern methods in F# must be in modules (even though the compiler won't stop you from trying to put them in a class).
It also appears that F#'s recursive types don't work between a module and a class, just classes.
Is there a solution to this problem that does not require declaring two different modules? Ideally I'd like to keep all of my platform invoke code organized into one module.

Well I know of one, because I had the same problem myself.
The thing is, it's kinda ugly I guess:
It involves a static reference that you set to the imported function later in the module.
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

Related

F#: get source files to evaluate automatically

I'm making a project where there are separate source files/modules that add functions to a single Dictionary contained in a higher level file. However, I find that nothing in these source files evaluates on its own, even functions that take no arguments/code that isn't even inside a function.
As a result nothing is being added to the Dictionary. Is there a way to forcibly evaluate complete function calls in a module automatically? I'll give an example of what I'm trying to do:
Registry.fs:
let private functions = Dictionary<string, MessageHandler>()
let add type handler =
functions.Add(type, handler)
Handler1.fs:
Registry.add "type1" (fun m -> ....
)
Handler2.fs:
Registry.add "type2" (fun m -> ....
)
I believe you need to see this relevant topic. Loose method calls would get compiled as method calls inside of a static constructor for the enclosing type/module, when the F# code gets compiled to IL. This would roughly be equivalent to the following C# code, just to see the picture:
static class Handler1 {
static Handler1() {
// this is the static constructor
Registry.add "type1" ....
}
}
In .NET static constructors are not eagerly initialized1. This means, if you want to cause the .NET runtime to call the Handler1 static constructor, you need to access a static member of the type Handler1.
An example of using the type in a static context would be to
Expose a sufficiently accessible static member/method:
module Handler1 =
[<Literal>]
let Name = "Handler1"
Access that static member from your code, such as the main method:
[<EntryPoint>]
let main args =
printf Handler1.Name
The above line will force the .NET runtime to load the Handler1 type's static context, which will result in invoking the static constructor if the type is encoutered by your code for the first time. If your code never encounters a given type's static context (any static member or method), then it will never be initialized -- the static constructors will never get called.
This behaviour is by design of the .NET framework (and that is regardless of the chosen language -- C#, F#, VB, others -- they all compile to similar IL). The point is to not allocate unnecessary resources by types that are never actually used.
1 Until .NET 4, static type context was initialized when the given type was first encountered by the executing code, regardless if the user code is interacting with instace or static members of that type. After .NET 4, this slightly changed -- the static context is initialized only when the user code interacts with static members of the type.

Overriding static properties in F# with extension methods

F# extension methods can be defined on types with the same name and type signature as existing instance and static methods to effectively override the default implementation of these methods, however I can't get this to work on static properties.
In particular, I'm trying to create an extension method for DateTime that returns a more precise time as follows:
#nowarn "51"
open System
module DateTimeExtensions =
open System.Runtime.InteropServices
[<DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)>]
extern void private GetSystemTimePreciseAsFileTime(int64*)
type System.DateTime with
// example showing that static methods can be overridden
static member IsLeapYear(_: DateTime) =
printfn "Using overridden IsLeapYear!"
true
// more accurate UtcNow method (note: not supported by older OS versions)
static member UtcNow =
printfn "Using overridden UtcNow!"
let mutable fileTime = 0L
GetSystemTimePreciseAsFileTime(&&fileTime)
DateTime.FromFileTimeUtc(fileTime)
However, the output when executing
open DateTimeExtensions
let _ = DateTime.IsLeapYear(DateTime.UtcNow)
is just
Using overridden IsLeapYear!
which shows that the static method 'override' is working, but not the static property.
(Note: I'm using F# 4.0)
This statement seems to be incorrect:
F# extension methods can be defined on types with the same name and
type signature as existing instance and static methods to effectively
override the default implementation of these methods, however I can't
get this to work on static properties.
No, they don't override.
You might be confused because in fact your signature of IsLeapYear is wrong, it should take an integer, that's why it works I mean you are not overriding anything, just adding a new (extension) method.
If you try it with the original signature you'll see that it doesn't work either:
type System.DateTime with
// example showing that static methods can NOT be overridden
static member IsLeapYear(_: int) =
printfn "Using overridden IsLeapYear!"
false
> DateTime.IsLeapYear(2000);;
val it : bool = true
Which is consistent with the behavior of the static property extension.
Anyway I'm not sure why it was decided not to override, if there was such decision at all when designing the language. I think it would be an interesting feature and if there is a good reason not to implement it at least it should emit a warning saying that since the method already exists it will never be called.
Maybe I will open an issue or a suggestion for the F# compiler.

Why does the F# compiler give an error for one case but not the other?

I'm working on a platform invoke call from F#, and I am getting a compiler error I really can't make that much sense out of. First, let me show the C signature of what I am doing:
int Foo(
ULONG_PTR *phHandle,
DWORD flags
);
In F#, I think the correct way to invoke this natively is as so:
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
[<Out>]nativeint& phHandle,
uint32 flags
)
If I try to call this in a class, I get a compilation error when calling it like so:
type Class1() =
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
member this.Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
The error is:
A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
Weirdly, when I do this all in a module, the compilation errors go away:
module Module1 =
[<DllImport("somedll.dll")>]
extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
let Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
Why does this compile as a module, but not as a class?
I don't think it's valid to define an extern method within a class in F#.
If you pull up the F# 3.0 language specification and search for DllImport, near the bottom is a table listing some special attributes and how they can be used. The text for [<DllImport>] says:
When applied to a function definition in a module, causes the F# compiler to ignore the implementation of the definition, and instead compile it as a CLI P/Invoke stub declaration.
That seems to indicate that it's only valid to declare extern methods (that use [<DllImport>]) on functions defined in a module; it doesn't say anything about class members though.
I think you're running into a compiler bug. Please submit this code to fsbugs#microsoft.com so they can fix the error message emitted by the compiler -- it should really be giving you an error about defining an extern method in a class since that's not allowed by the language spec.
Whether this is a bug not withstanding, maybe this is what's going on: If APlatformInvokeCall were considered a static member function, that member have a single argument of tuple type. Tuples are compiled into objects of generic type (see here, at the bottom, or 5.1.3 in the spec). In this case that tuple is
System.Tuple<nativeint&, uint32>
But ECMA 335 II.9.4 says you can't instantiate generic types at byref types. This explains the error reported.
This explanation fits the fact mentioned above that Class1 works (well, compiles) if you modify the extern declaration and call to take instead a single argument. It also fits the fact that the module version works, since in that version there is no considering APlatFormInvokeCall a member function.
The simple solution is to check the spec, here is the class definition grammar:
type type-name pat_opt as-defn)opt =
class
class-inherits-decl_opt
class-function-or-value-defns_opt
type-defn-elements
end
then we have
class-function-or-value-defn :
attributes_opt staticopt let rec_opt function-or-value-defns
attributes_opt staticopt do expr
which doesn't allow extern.
and
type-defn-element :
member-defn
interface-impl
interface-signature
which isn't what you want either.
As a result, we can see that using extern as you are trying to use it can't be done inside a class.

F# top level do binding

I have a file with a module with some routines that take parameters and return unit, these routines have side-effects. I noticed that when accessing these f# routines from c# they're actually properties of type unit and when I try to access 1 property, it runs all properties in the module.
From the F# documentation all top level do bindings are run on type initialization.
What is the preferred way to write functions that should not be run on type initialization but are also not associated with other state i.e. a class with functions and member variables?
Should I put these functions inside a type and just have no records in the type?
Code example:
namespace test_space
open System.Diagnostics;
module test =
let test_1 =
Debug.WriteLine ("One")
let test_2 =
Debug.WriteLine ("Two")
I'm running this code with C#:
static void Main (string [] args)
{
Object o;
o = test.test_2;
}
And the output is:
One
Two
The problem is you didn't create functions but value bindings. test_1 is a value. test_1() is a function of type unit -> unit. Make sure you put () after the function name.
I don't fully understand the scenario you're describing - F# functions declared in a module will generally appear as methods and values will appear as properties. The code that is executed when you first access module (type initialization) is the initialization of values.
If you write just:
module Foo =
let Operation () =
printfn "hello"
...then calling Operation will be a method and calling Foo.Operation() will run the side-effect. If you can post some code that behaves unexpectedly, then someone can explain it.
Anyway, if you want to be sure about the behavior, you can write operations as static members of a class:
type Foo =
static member Operation() =
printfn "hello"
Then you can be sure that F# will compile them as static members of a class in a predictable way.

Refactoring many identical DllImport declarations

I have a module which contains an interface to a native DLL; it looks like this:
// nvtt.dll binding module
module private NvTextureTools =
type NvttInputOptions = IntPtr
[<DllImport("nvtt", CallingConvention = CallingConvention.Cdecl)>]
extern NvttInputOptions nvttCreateInputOptions()
[<DllImport("nvtt", CallingConvention = CallingConvention.Cdecl)>]
extern void nvttDestroyInputOptions(NvttInputOptions)
[<DllImport("nvtt", CallingConvention = CallingConvention.Cdecl)>]
extern void nvttSetInputOptionsAlphaMode(NvttInputOptions, AlphaMode alphaMode)
[<DllImport("nvtt", CallingConvention = CallingConvention.Cdecl)>]
extern void nvttSetInputOptionsGamma(NvttInputOptions, float inputGamma, float outputGamma)
[<DllImport("nvtt", CallingConvention = CallingConvention.Cdecl)>]
extern void nvttSetInputOptionsWrapMode(NvttInputOptions, WrapMode mode)
(there are 5x more functions, but this should give the general idea).
Is there any way to specify the DllImport parameters just once? As far as I understand, I can't inherit from DllImport (it's sealed, and anyway I don't think it would work if it was not), and I can't use reflection to add the necessary attributes because I need them at compilation time.
I could make a brand new class with P/Invoke methods using reflection, but this will make calling them cumbersome.
Any thoughts?
I don't know about F#, but in C# you can do something like:
static const string DllName = "nvtt";
[DllImport(DllName, other params...)]
some function signature
[DllImport(DllName, other params...)=
some function signature
So that way the actual string is only declared once - the DllImport attributes themselves all still look a lot alike, but it makes changing things easier. I think you could do the same with CallingConvention, but I've never tried it with an enum.
Just in case you are using Visual Studio - it is possible to create a T4 template and generate all those nasty attributes. This is not an F# or VS specific solution however, any code generating tool would work.

Resources