开发者

Proper IntPtr use in C#

I think I understand the use of IntPtr, though I'开发者_Python百科m really not sure.

I copied the IDisposable pattern from MSDN just to see what I could get from it, and while I understand it for the most part, I have no idea how to implement an IntPtr properly, or even understand what it is that it's supposed to "point" to, or reference. On top of that, I have no idea how to even assign or cast an integer, string, char, double, etc. to an IntPtr to create a pointer out of it.

Also, does IntPtr require unsafe code use?

Anyway, here's some code just to paint a picture of what I'm talking about:

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()
        { 

        }
    }
}

Also, could someone tell me what the point of the component here is, exactly? I'm also having trouble wrapping my head around this concept as well.


You can use IntPtr objects this way:

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);

You can explore other Marshal method to understand how to write string, doubles and etc to IntPtr.

So words about your sample code - its not a good idea to dispose external allocated unmanaged object. You should dispose only object which you have allocated in class constructor. This is not strict rule but some kind of good practice.


IntPtr (this link actually says much of what I do) is a special form of integer that is the size of the pointer for the current bit-ness of the process -- the size is 4 bytes in 32bit x86, 8 bytes in 64bit x86, as this corresponds with the size a pointer.

While it can refer to a location in memory, it doesn't need to. As in the posted code, it could just refer to a handle or other opaque number. It is important because of the size changes in P/Invoked system calls (system calls use constant-sized integer while some depend on the architecture and pointers are always architecture dependent). An IntPtr does not need to be disposed of itself, but the opaque number contained in it may refer to a resource that does need releasing; this is all part of the API contract with where the value was obtained.

See new IntPtr(long) and IntPtr.ToInt32/ToInt64 for conversions to/from a standard numeric type (on a 64-bit environment it is possible that ToInt32 will throw an overflow exception).

And no, while obtaining a value for the IntPtr (e.g. calling P/Invoked function) may require the appropriate security permissions, there is no unsafe code required (see the link or what unsafe allows) -- but arguably anything that talks to native code is "unsafe" as it can cause a nice process crash ;-)

Happy coding.


An IntPtr is only a value type which size matches the size of a pointer on the target platform. You need to use it mainly when dealing with unmanaged pointers. An IntPtr itself cannot be disposed, because it only represents a location in memory. Your cleanup needs to be specific to the object referred to by the IntPtr. Say you have an unmanaged function that needs a window handle to do its work. In this case you can use the property Control.Handle to get a pointer to the window handle of the control. To properly cleanup the control and its underlying window you do not have to take care of the IntPtr refering to the unmanaged handle, but instead dispose the control.

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

private void Foo()
{
    Form form = new Form();
    // ...
    DoSomethingWithWindowHandle(form.Handle);
    // ...
    form.Dispose();
}


IntPtr is an integer the size of a pointer, 32 bits on 32 bit systems and 64 bits on 64 bit systems. It is typically used to wrap a pointer or handle to be handed off to an unmanaged function as you have done. "unsafe" means you are using pointers in your C# code, so IntPtrs outside of unsafe blocks or with out allowing unsafe code to be compiled.

I also can't tell you what the point of that component but it really, really shouldn't exist. Handles should be owned by an object the exposes the functionality that the handle represents and be responsible for managing that handle's life cycle. A class that just arbitrarily closes handles that it didn't allocate is frighteningly bad design.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜