17

本当によくわかりませんが、IntPtr の使用法は理解していると思います。

MSDN から IDisposable パターンをコピーして、そこから何が得られるかを確認しました。ほとんどの部分は理解していますが、IntPtr を適切に実装する方法がわかりません。 」へ、または参照。その上、整数、文字列、char、double などを IntPtr に代入またはキャストして、そこからポインターを作成する方法さえわかりません。

また、IntPtr では安全でないコードを使用する必要がありますか?

とにかく、ここに私が話していることの絵を描くためのいくつかのコードがあります:

namespace Utilities
{   
    class Disposer : IDisposable
    {

        private IntPtr handle;

        private Component component = new Component(); 

        private bool disposed = false;

        public Disposer(IntPtr handle)
        {
            this.handle = handle;

        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if(!this.disposed)
            {
                if (disposing)
                {
                    component.Dispose(); 
                }
                CloseHandle(handle);

                handle = IntPtr.Zero;

                disposed = true;

            }
        }

        [System.Runtime.InteropServices.DllImport("Kernal32")]
        private extern static Boolean CloseHandle(IntPtr handle);
    }



    public unsafe class ExecuteMain
    {
        Object nuller = new Object();

        byte boa = 0;

        byte *blargh = boa;

        public static void Main()
        { 

        }
    }
}

また、ここのコンポーネントの要点を正確に誰か教えてもらえますか? 私もこの概念に頭を悩ませています。

4

4 に答える 4

20

IntPtr オブジェクトを次のように使用できます。

        int test = 55;

        // Allocating memory for int
        IntPtr intPointer = Marshal.AllocHGlobal(sizeof(int));

        Marshal.WriteInt32(intPointer,test);

        // sending intPointer to unmanaged code here

        //Test reading of IntPtr object
        int test2 = Marshal.ReadInt32(intPointer); // test2 would be equal 55

        // Free memory
        Marshal.FreeHGlobal(intPointer);

Marshal文字列、double などを IntPtr に書き込む方法を理解するために、他の方法を調べることができます。

サンプルコードについての言葉 - 外部に割り当てられた管理されていないオブジェクトを破棄することはお勧めできません。クラスコンストラクターで割り当てたオブジェクトのみを破棄する必要があります。これは厳密な規則ではありませんが、ある種の良い習慣です。

于 2011-05-23T06:31:49.793 に答える
7

IntPtr(このリンクは実際に私がしていることの多くを述べています)プロセスの現在のビットネスのポインターのサイズである整数の特別な形式です-サイズは32ビットx86で4バイト、64ビットx86で8バイトです。これはポインタのサイズに対応するためです。

メモリ内の場所を参照できますが、その必要はありません。投稿されたコードのように、ハンドルまたはその他の不透明な番号を参照することができます。P/Invoked システム コールのサイズが変更されるため、これは重要です (システム コールは定数サイズの整数を使用しますが、一部はアーキテクチャに依存し、ポインタは常にアーキテクチャに依存します)。はそれ自体を破棄するIntPtr必要はありませんが、それに含まれる不透明な番号は、解放が必要なリソースを参照している可能性があります。これはすべて、値が取得された場所との API コントラクトの一部です。

new IntPtr(long)標準数値型との変換については、 とを参照してくださいIntPtr.ToInt32/ToInt64(64 ビット環境ではToInt32、オーバーフロー例外がスローされる可能性があります)。

いいえ、IntPtr(P/Invoked 関数の呼び出しなど) の値を取得するには適切なセキュリティ アクセス許可が必要な場合がありますが、unsafeコードは必要ありません (リンクまたは何unsafeが許可されているかを参照してください)。 " プロセスがクラッシュする可能性があるためです ;-)

ハッピーコーディング。

于 2011-05-23T06:24:27.627 に答える
5

AnIntPtrは、サイズがターゲット プラットフォームのポインターのサイズと一致する値型のみです。主にアンマネージ ポインターを扱うときに使用する必要があります。IntPtrメモリ内の場所を表すだけなので、それ自体を破棄することはできません。クリーンアップは、 によって参照されるオブジェクトに固有である必要がありますIntPtr。作業を行うためにウィンドウ ハンドルが必要なアンマネージ関数があるとします。この場合、プロパティControl.Handleを使用して、コントロールのウィンドウ ハンドルへのポインターを取得できます。コントロールとその下にあるウィンドウを適切にクリーンアップするにはIntPtr、アンマネージ ハンドルへの参照を処理する必要はなく、代わりにコントロールを破棄します。

[DllImport("UnmanagedLibrary.dll")]
private static void DoSomethingWithWindowHandle(IntPtr windowHandle);

private void Foo()
{
    Form form = new Form();
    // ...
    DoSomethingWithWindowHandle(form.Handle);
    // ...
    form.Dispose();
}
于 2011-05-23T06:24:26.610 に答える
2

IntPtr は、ポインターのサイズの整数で、32 ビット システムでは 32 ビット、64 ビット システムでは 64 ビットです。これは通常、アンマネージ関数に渡されるポインターまたはハンドルをラップするために使用されます。「安全でない」とは、C# コードでポインターを使用していることを意味するため、IntPtrs は安全でないブロックの外側にあるか、安全でないコードのコンパイルを許可していません。

また、そのコンポーネントが何を意味するのかはわかりませんが、実際には存在すべきではありません。ハンドルは、ハンドルが表す機能を公開するオブジェクトによって所有され、そのハンドルのライフ サイクルの管理を担当する必要があります。割り当てられていないハンドルを恣意的に閉じるだけのクラスは、恐ろしく悪い設計です。

于 2011-05-23T06:23:09.977 に答える