声明nativeptr类型
我想知道是否可以在 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:操作可能会破坏运行时的稳定性。)
注释的代码运行良好(可以找到此处),但我的观点是用 F#(而不是 C#)对其进行编码。
我首先想使用 nativeptr
的原因是它实际上是 MemCpy
委托的前两个参数的类型(与 void 匹配) *
类型)并且有点想模仿它。
编辑2:
根据 kvb 的编辑,我修改了代码以使用静态成员(如 C# 版本)的类型托管委托创建,现在它可以工作了。 我不使用带有非托管约束的版本,但是这个版本,因为我实际上需要 blit 结构数组:
type blitDelegate = delegate of nativeint * nativeint * uint32 -> unit
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据您的描述,我不清楚您为什么需要
nativeptr
。本质上,nativeptr<'t>
只是nativeint
的一个薄包装器,带有一些用于对指针进行算术运算的帮助器。由于您不太可能拥有一个unit
数组,因此我不知道这实际上对您有什么帮助。也许如果你展示更多的代码,会更容易给出更令人满意的答案。编辑
我认为你几乎一切都做对了。但是,匿名托管的 DynamicMethod 必须是可验证的,而 cpblk 操作码永远无法验证。尝试为
DynamicMethod
使用不同的构造函数将其托管在类型或模块上。From your description, it's not clear to me why you'd like a
nativeptr<unit>
. Essentially,nativeptr<'t>
is just a thin wrapper overnativeint
with some helpers for doing arithmetic on the pointer. Since you're unlikely to have an array ofunit
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 thecpblk
opcode is never verifiable. Try using a different constructor forDynamicMethod
to host it on a type or module.