Question

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
Was it helpful?

Solution

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 units, 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 DynamicMethods 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top