声明nativeptr <unit> type </unit>

时间:2010-12-28 19:40:03

标签: f# interop native c#-to-f# unit-type

我想知道在F#中是否可以声明类型:

nativeptr<unit>

这似乎不可能(编译器抱怨“泛型构造要求类型'unit'是非托管类型”)。我可以使用一种解决方法吗?

最终目标是声明我自己的blitDelegate,以便将操作码Cpblk暴露给我的一些F#代码。

感谢。

修改

以下是我根据kvb的回答尝试的内容:

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)

然后我从类成员中调用此代码:

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)

这会导致blit运行时错误( System.Security.VerificationException:Operation可能会破坏运行时的稳定性。

评论代码效果很好(可以找到here)但我的观点是用F#编码(不是C#)。

我之前想要使用nativeptr<unit>的原因是它实际上是MemCpy委托的两个第一个参数的类型(匹配void*类型)并且有点想要模仿它。

EDIT2:

基于kvb的编辑,我修改了我的代码以使用静态成员(如C#版本)在一个类型中托管委托创建,现在它可以正常工作。 我不使用具有非托管约束的版本但是这个,因为我实际上需要blit结构数组:

type blitDelegate = delegate of nativeint * nativeint * uint32 -> unit

1 个答案:

答案 0 :(得分:2)

根据您的描述,我不清楚为什么您喜欢nativeptr<unit>。从本质上讲,nativeptr<'t>只是nativeint上的一个瘦包装器,有一些帮助器可以对指针进行算术运算。既然你不太可能拥有unit的数组,我看不出这对你有什么帮助。也许如果你展示更多的代码,那么更容易给出更满意的答案。

修改

我认为你几乎做的一切都是正确的。但是,匿名托管的DynamicMethod必须是可验证的,并且cpblk操作码永远不可验证。尝试使用DynamicMethod的不同构造函数将其托管在类型或模块上。