I've searched the internet far and wide but didn't find a good explanation.
My question is pretty simple.
I have a DLL which has a function called Initialize and one of the parameters is a pointer that will receive a handle to be used with subsequent calls. Another parameter is a string which I will list for completeness. The signature I'm using is (in its simple form):
[DllImport(MyDll)]
static extern bool Initialize([In] string name, out IntPtr handle);
The signature in the DLL itself is written as: Initialize(LPTSTR name, HANDLE handle)
with the comment "HANDLE: Pointer to a location that will receive the handle".
And subsequent calls are in the form of
[DllImport(MyDll)]
static extern bool DoSomething(IntPtr handle, uint randomParameter);
I have been reading about SafeHandle
and I was wondering if I could use it to substite for my IntPtr handle. And if I can, how do I do it? Extending the abstract SafeHandle class isn't an issue, but can I directly substitute my IntPtr for SafeHandle (and use default Marshalling) or do I need to do something extra?
The SafeHandle class provides critical finalization of handle resources, preventing handles from being reclaimed prematurely by garbage collection and from being recycled by Windows to reference unintended unmanaged objects.
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.
The IntPtr type can be used by languages that support pointers and as a common means of referring to data between languages that do and do not support pointers. IntPtr objects can also be used to hold handles. For example, instances of IntPtr are used extensively in the System. IO.
You can find a more complete answer about the difference between SafeHandle
and IntPtr
here: IntPtr, SafeHandle and HandleRef - Explained
However, to summarize, IntPtr
should be used where the argument is actually a machine-size pointer - SafeHandle
should be used where the argument is actually a Win32 handle. These types are not generally interchangeable; the size of IntPtr
will vary on different architectures (32 bits on x86 and 64 bits on x64 and amd64). NOTE: Under the covers I believe SafeHandle
uses an IntPtr
as well).
Also, unlike IntPtr
, SafeHandle
actually performs disposal of resources when a type is garbage collected. This ensures that system resources are not leaked when your program is running (although you should Dispose()
of SafeHandle
instances early when possible). Note that SafeHandle
is actually abstract because there many different kinds of handles which require different approaches for proper disposal and handling.
In your specific case, you need to look at the documentation for the DLL you are calling. If it is a Win32 DLL, there may already be a SafeHandle type for it. If it's a third-party DLL, then you can roll your own SafeHandle implementation - assuming that in addition to Initialize()
there is some version of Release()
(or equivalent).
Some additional interesting tidbits about IntPtr vs SafeHandle can be found at:
Use SafeHandle to encapsulate native resources
SafeHandle Class Reference
SafeHandles and Critical Finalization
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With