如何在 C# 中固定指向托管对象的指针?

发布于 2024-11-27 02:20:16 字数 175 浏览 1 评论 0原文

非托管代码调用我的函数。在第一个函数中,我应该将指针传回我的托管对象。有时,后来我的一些其他函数会使用相同的指针作为参数之一来调用。我应该取消引用它并使用它来执行一些计算,然后如果不需要则将其处理掉。 简而言之,我需要固定该对象,以便 GC 不会移动它,直到我处理掉它。在 C# 中如何做到这一点? 提前致谢。

Unmanaged code calls my functions. In first function I should pass back pointer to my managed object. Sometimes later some of my other functions get called with that same pointer as one of parameters . I should dereference it and use it to perform some calculations and then if it is not needed dispose of it.
To cut the story short I need to pin that object so that GC won't move it til I dispose of it. How to do that in C# ?
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

再浓的妆也掩不了殇 2024-12-04 02:20:16

要在 C# 中固定对象,您可以使用带有第二个参数 GCHandleType.PinnedGCHandle.Alloc 方法。对象保持固定状态,直到使用 GCHandle.Free 方法释放 GCHandle 实例。

To pin an object in C#, you can use GCHandle.Alloc method with second parameter GCHandleType.Pinned. Object remains pinned until GCHandle instance is released using GCHandle.Free method.

左耳近心 2024-12-04 02:20:16

(大约 2022 年,Dotnet 6)

另一个答案不适用于托管对象。在运行时它会失败。这是将按照要求执行的代码。

public static class Pin
{

    /// <summary>
    /// use to obtain raw access to a managed object.  allowing pinning.
    /// <para>
    /// Usage:<code>fixed (byte* data = [AND_OPERATOR]GetRawObjectData(managed)){  }</code>
    /// </para>
    /// </summary>
    public static ref byte GetRawObjectData(object o)
    {
        //usage:  fixed (byte* data = &GetRawObjectData(managed)) { }
        return ref new PinnableUnion(o).Pinnable.Data;
    }

    [StructLayout(LayoutKind.Sequential)]
    sealed class Pinnable
    {
        public byte Data;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct PinnableUnion
    {
        [FieldOffset(0)]
        public object Object;

        [FieldOffset(0)]
        public Pinnable Pinnable;

        public PinnableUnion(object o)
        {
            System.Runtime.CompilerServices.Unsafe.SkipInit(out this);
            Object = o;
        }
    }
}

(Circa 2022, Dotnet 6)

The other answer doesn't work for managed objects. At runtime it will fail. Here is code that will do as requested.

public static class Pin
{

    /// <summary>
    /// use to obtain raw access to a managed object.  allowing pinning.
    /// <para>
    /// Usage:<code>fixed (byte* data = [AND_OPERATOR]GetRawObjectData(managed)){  }</code>
    /// </para>
    /// </summary>
    public static ref byte GetRawObjectData(object o)
    {
        //usage:  fixed (byte* data = &GetRawObjectData(managed)) { }
        return ref new PinnableUnion(o).Pinnable.Data;
    }

    [StructLayout(LayoutKind.Sequential)]
    sealed class Pinnable
    {
        public byte Data;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct PinnableUnion
    {
        [FieldOffset(0)]
        public object Object;

        [FieldOffset(0)]
        public Pinnable Pinnable;

        public PinnableUnion(object o)
        {
            System.Runtime.CompilerServices.Unsafe.SkipInit(out this);
            Object = o;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文