IntPtr 和避免不安全代码

发布于 2024-09-11 15:13:28 字数 453 浏览 5 评论 0原文

我有一个需要 IntPtr 的外部库。有没有安全的方法可以做到这一点...

int BytesWritten = 0;
Output.WriteBytes(buffer, new IntPtr(&BytesWritten));

...而不必使用“不安全”代码?我对 IntPtrs 不太熟悉,但我想做这样的事情:

fixed int BytesWritten = 0;
Output.WriteBytes(buffer, IntPtr.GetSafeIntPtr(ref BytesWritten));

...以这样的方式我不需要使用 /unsafe 进行编译。

我无法更改 WriteBytes 函数,它是一个外部函数。

似乎“ref int”和 IntPtr 之间应该存在某种类型的转换,但我没有运气找到它。

I have an external library that takes an IntPtr. Is there any safe way to do this...

int BytesWritten = 0;
Output.WriteBytes(buffer, new IntPtr(&BytesWritten));

...without having to use 'unsafe' code? I'm not that familiar with IntPtrs, but I'd like to do something like this:

fixed int BytesWritten = 0;
Output.WriteBytes(buffer, IntPtr.GetSafeIntPtr(ref BytesWritten));

...in such a way that I don't need to compile with /unsafe.

I can't change the WriteBytes function, it's an external function.

It seems like there should be some sort of cast between 'ref int' and IntPtr, but I have not had luck finding it.

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

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

发布评论

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

评论(3

一梦浮鱼 2024-09-18 15:13:28

我假设 Output.WriteBytes 是一个 [DllImport] 方法。可以贴一下声明吗?

您应该能够通过将最后一个参数声明为 out int 而不是 IntPtr 来避免使用指针——让 P/Invoke 编组器完成剩下的工作。

I assume that Output.WriteBytes is a [DllImport] method. Can you post the declaration?

You should be able to avoid the pointer by declaring the last parameter as out int instead of IntPtr -- let the P/Invoke marshaller do the rest.

扭转时空 2024-09-18 15:13:28

是的,有。您可以将 P/Invoke 用于您的代码。它会自动为您创建指针。像这样的东西:

[DllImport("yourlib", SetLastError=true)]
static extern bool WriteBytes(
    [MarshalAs(UnmanagedType.LPArray)]
    byte [] buffer,
    ref int BytesWritten);

(我添加了数组作为奖励)。有关 P/Invoke 的更多信息,以及大量示例,请访问 pinvoke.net

上面的每个参数都可以取出outinref。 Out 和 ref 参数被转换为指针,其中 ref 参数是双向的。

Yes, there is. You can use P/Invoke for your code. It will create the pointer for you automagically. Something like this:

[DllImport("yourlib", SetLastError=true)]
static extern bool WriteBytes(
    [MarshalAs(UnmanagedType.LPArray)]
    byte [] buffer,
    ref int BytesWritten);

(I added the array as a bonus). More info on P/Invoke can be found, with gazillion examples, at pinvoke.net.

Each parameter above can take out, in and ref. Out and ref parameters are translated as pointers, where an ref-parameter is two-way.

懒猫 2024-09-18 15:13:28

这是一个将为您提供安全的 IntPtr 实现的类。它派生自 .NET 框架提供的 SafeHandleZeroOrMinusOneIsInvalid 类。

/// <summary>
/// IntPtr wrapper which can be used as result of
/// Marshal.AllocHGlobal operation.
/// Call Marshal.FreeHGlobal when disposed or finalized.
/// </summary>
class HGlobalSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    /// <summary>
    /// Creates new instance with given IntPtr value
    /// </summary>
    public HGlobalSafeHandle(IntPtr ptr) : base(ptr, true)
    {
    }

    /// <summary>
    /// Creates new instance with zero IntPtr
    /// </summary>
    public HGlobalSafeHandle() : base(IntPtr.Zero, true)
    {
    }

    /// <summary>
    /// Creates new instance which allocates unmanaged memory of given size 

  /// Can throw OutOfMemoryException
    /// </summary>
    public HGlobalSafeHandle(int size) :
        base(Marshal.AllocHGlobal(size), true)
    {
    }


    /// <summary>
    /// Allows to assign IntPtr to HGlobalSafeHandle
    /// </summary>
    public static implicit operator HGlobalSafeHandle(IntPtr ptr)
    {
        return new HGlobalSafeHandle(ptr);
    }

    /// <summary>
    /// Allows to use HGlobalSafeHandle as IntPtr
    /// </summary>
    public static implicit operator IntPtr(HGlobalSafeHandle h)
    {
        return h.handle;
    }

    /// <summary>
    /// Called when object is disposed or finalized.
    /// </summary>
    override protected bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(handle);
        return true;
    }

    /// <summary>
    /// Defines invalid (null) handle value.
    /// </summary>
    public override bool IsInvalid
    {
        get
        {
            return (handle == IntPtr.Zero);
        }
    }
}

Here is a class that will provide you with a safe IntPtr implementation. It derives from the SafeHandleZeroOrMinusOneIsInvalid class, provided by the .NET framework.

/// <summary>
/// IntPtr wrapper which can be used as result of
/// Marshal.AllocHGlobal operation.
/// Call Marshal.FreeHGlobal when disposed or finalized.
/// </summary>
class HGlobalSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    /// <summary>
    /// Creates new instance with given IntPtr value
    /// </summary>
    public HGlobalSafeHandle(IntPtr ptr) : base(ptr, true)
    {
    }

    /// <summary>
    /// Creates new instance with zero IntPtr
    /// </summary>
    public HGlobalSafeHandle() : base(IntPtr.Zero, true)
    {
    }

    /// <summary>
    /// Creates new instance which allocates unmanaged memory of given size 

  /// Can throw OutOfMemoryException
    /// </summary>
    public HGlobalSafeHandle(int size) :
        base(Marshal.AllocHGlobal(size), true)
    {
    }


    /// <summary>
    /// Allows to assign IntPtr to HGlobalSafeHandle
    /// </summary>
    public static implicit operator HGlobalSafeHandle(IntPtr ptr)
    {
        return new HGlobalSafeHandle(ptr);
    }

    /// <summary>
    /// Allows to use HGlobalSafeHandle as IntPtr
    /// </summary>
    public static implicit operator IntPtr(HGlobalSafeHandle h)
    {
        return h.handle;
    }

    /// <summary>
    /// Called when object is disposed or finalized.
    /// </summary>
    override protected bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(handle);
        return true;
    }

    /// <summary>
    /// Defines invalid (null) handle value.
    /// </summary>
    public override bool IsInvalid
    {
        get
        {
            return (handle == IntPtr.Zero);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文