声明nativeptr类型

发布于 2024-10-09 15:26:40 字数 2108 浏览 0 评论 0原文

我想知道是否可以在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

总以为 2024-10-16 15:26:40

根据您的描述,我不清楚您为什么需要 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 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文