6

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の間に何らかのキャストがあるはずですが、私はそれを見つけることができませんでした。

4

3 に答える 3

3

それOutput.WriteBytes[DllImport]方法だと思います。宣言を投稿できますか?

out int代わりに最後のパラメーターを宣言することで、ポインターを回避できるはずですIntPtr。残りはP/Invokeマーシャラーに任せてください。

于 2010-07-26T17:43:19.153 に答える
2

はいあります。コードにP/Invokeを使用できます。それは自動的にあなたのためのポインタを作成します。このようなもの:

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

(ボーナスとしてアレイを追加しました)。P / Invokeの詳細については、数え切れないほどの例を含めて、pinvoke.netを参照してください。

上記の各パラメータは、、およびをとることがoutできinますref。Outパラメーターとrefパラメーターはポインターとして変換されます。ここで、refパラメーターは双方向です。

于 2010-07-26T17:41:36.593 に答える
1

これは、安全なIntPtr実装を提供するクラスです。これは、.NETFrameworkによって提供される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);
        }
    }
}
于 2010-07-26T17:47:04.430 に答える