我想我理解使用IntPtr,虽然我真的不确定。
我从MSDN复制IDisposable模式只是为了看看我能从中得到什么,虽然我在大多数情况下理解它,但我不知道如何正确实现IntPtr,或者甚至不知道它是什么意思“指向”或引用。最重要的是,我不知道如何为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()
{
}
}
}
另外,有人可以告诉我这里的组件究竟是什么意思吗?我也很难绕过这个概念。
答案 0 :(得分:12)
您可以这样使用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
方法,以了解如何将字符串,双精度等写入IntPtr。
关于示例代码的说法 - 处理外部分配的非托管对象不是一个好主意。您应该只处置在类构造函数中分配的对象。这不是严格的规则,而是某种良好的做法。
答案 1 :(得分:4)
IntPtr
(这个链接实际上说的是我做的很多)是一个特殊形式的整数,它是进程的当前位指针的大小 - 大小为32位x86中的4个字节,64位x86中的8个字节,因为这与指针的大小相对应。
虽然它可以引用内存中的位置,但它不需要。与发布的代码一样,它可以仅引用句柄或其他不透明数字。这很重要,因为P / Invoked系统调用的大小更改(系统调用使用常量大小的整数,而某些依赖于体系结构,指针总是依赖于体系结构)。 IntPtr
不需要自行处理,但其中包含的不透明数字可能指的是需要释放的资源;这是获得价值的API合同的所有部分。
有关与标准数字类型之间的转换,请参阅new IntPtr(long)
和IntPtr.ToInt32/ToInt64
(在64位环境中,ToInt32
可能会引发溢出异常。)
不,虽然获取IntPtr
的值(例如调用P / Invoked函数)可能需要相应的安全权限,但不需要unsafe
代码(请参阅链接或{{} 1}}允许) - 但可以说任何与本机代码对话的东西都是“不安全的”,因为它会导致一个很好的进程崩溃; - )
快乐的编码。
答案 2 :(得分:3)
IntPtr
只是一个值类型,其大小与目标平台上指针的大小相匹配。您需要主要在处理非托管指针时使用它。 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();
}
答案 3 :(得分:2)
IntPtr是一个指针大小的整数,32位系统上的32位和64位系统上的64位。它通常用于包装指针或句柄,以便像您一样将其移交给非托管函数。 “unsafe”意味着你在C#代码中使用指针,因此IntPtrs不安全的块之外或者不允许编译不安全的代码。
我也无法告诉你该组件的重点是什么,但真的,真的不应该存在。句柄应由对象拥有,公开句柄所代表的功能,并负责管理句柄的生命周期。一个只是随意关闭它没有分配的句柄的类是可怕的糟糕设计。