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?
Designed from the ground up to prioritize low-observability, the F-35 may be the stealthiest fighter in operation today. It uses a single F135 engine that produces 40,000 lbs. of thrust with the afterburner engaged, capable of pushing the sleek but husky fighter to speeds as high as Mach 1.6.
All that makes the F-35 among the world's most advanced multi-role fighters flying today. Powered by F135-PW-100 engines that provide 40,000 pounds of maximum propulsion, the combat aircraft has a range of 1,200 nautical miles, and can reach speeds of upwards of Mach 1.6 (1,200 mph).
In aerial combat, it has a staggering 100 confirmed kills and zero losses. In an earlier report by The EurAsian Times, a USAF pilot had admitted that the 'mighty' F-22 Raptors would avoid a dogfight with Sukhoi Su-35 jets and instead call on the F-15 fighters to tackle the Russian threats.
The F-35B Lightning II is the Marine Corps variant of the Joint Strike Fighter and features a vertical lift fan and pivoting engine nozzle to deliver vertical landing and short takeoff capability to expeditionary airfields. The F-35 will replace AV-8B Harrier IIs in the Marine Corps inventory.
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 [email protected]
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With