I'd like to know if it's possible in F# to declare the type:
nativeptr<unit>
This seems not possible (compiler complains with "A generic construct requires that the type 'unit' is an unmanaged type"). Is there a workaround I could use?
The ultimate goal is to declare my own blitDelegate for exposing the opcode Cpblk
to some of my F# code.
Thanks.
Edit:
Here's what I've tried based on kvb's answer:
type blitDelegate<'T when 'T : unmanaged> = delegate of nativeptr<'T> * nativeptr<'T> * uint32 -> unit
let createBlitDelegate<'T when 'T : unmanaged>() =
let dm = new DynamicMethod("blit",
typeof<System.Void>,
[| typeof<nativeptr<'T>>; typeof<nativeptr<'T>>; typeof<uint32> |])
let ilGenerator = dm.GetILGenerator()
ilGenerator.Emit(OpCodes.Ldarg_0)
ilGenerator.Emit(OpCodes.Ldarg_1)
ilGenerator.Emit(OpCodes.Ldarg_2)
ilGenerator.Emit(OpCodes.Cpblk)
ilGenerator.Emit(OpCodes.Ret)
dm.CreateDelegate(typeof<blitDelegate<'T>>) :?> blitDelegate<'T>
let blit (blitDel:blitDelegate<'T>) dst src byteWidth = blitDel.Invoke(dst, src, byteWidth)
Then I call this code from a class member like that:
let dst = //get nativeint destination address
let src = //get nativeint source address
let bd = createBlitDelegate<'T>()
let tdst = NativePtr.ofNativeInt<'T> dst
let tsrc = NativePtr.ofNativeInt<'T> src
do blit bd tdst tsrc (uint32 size)
//Program.MemCpy.Invoke(dst.ToPointer(), dst.ToPointer(), uint32 size)
This results in a runtime error at blit (System.Security.VerificationException: Operation could destabilize the runtime.)
The commented code works well (and can be found here) but my point was to code it in F# (not C#).
The reason why I wanted to use at first a nativeptr<unit>
is that it is actually the type of the two first arguments of MemCpy
delegate (that matches void*
type) and somewhat wanted to mimic it.
Edit2:
Based on kvb's edit, I modified my code to host the delegate creation in a type using static members (like the C# version) and it now works. I don't use the version with the unmanaged constraint but this one, since I actually need to blit array of structs:
type blitDelegate = delegate of nativeint * nativeint * uint32 -> unit
From your description, it's not clear to me why you'd like a nativeptr<unit>
. Essentially, nativeptr<'t>
is just a thin wrapper over nativeint
with some helpers for doing arithmetic on the pointer. Since you're unlikely to have an array of unit
s, I don't see how this actually helps you, though. Perhaps if you show more of your code it will be easier to give a more satisfactory answer.
EDIT
I think you're doing almost everything right. However, anonymously hosted DynamicMethod
s must be verifiable, and the cpblk
opcode is never verifiable. Try using a different constructor for DynamicMethod
to host it on a type or module.