我想知道在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
答案 0 :(得分:2)
根据您的描述,我不清楚为什么您喜欢nativeptr<unit>
。从本质上讲,nativeptr<'t>
只是nativeint
上的一个瘦包装器,有一些帮助器可以对指针进行算术运算。既然你不太可能拥有unit
的数组,我看不出这对你有什么帮助。也许如果你展示更多的代码,那么更容易给出更满意的答案。
修改强>
我认为你几乎做的一切都是正确的。但是,匿名托管的DynamicMethod
必须是可验证的,并且cpblk
操作码永远不可验证。尝试使用DynamicMethod
的不同构造函数将其托管在类型或模块上。