您的位置:首页 > 其它

使用指针指向托管内存,和使用句柄指向本地内存

2007-03-26 13:32 387 查看
在编写托管代码的过程中,往往需要利用非托管内存的简单分配删除的特性,例如想生成一个大对象,使用之后想马上释放,就很适合在非托管内存中建立这个大对象。建立后,在托管代码中,需要一个句柄能指向这个大对象的内存,如下图所示。



这个过程可以使用Marshal类的AllocHGlobal方法,这个方法使用 GlobalAlloc 从进程的非托管内存中分配内存,并操作非托管内存。


Marshal::AlloclHGlobal()

相反,我们有时也希望在托管内存中分配内存,并在本地内存的指针指向它。例如在编写托管代码时,需要使用原来的库函数。但是托管代码所分配的内存都在托管堆中,本地堆中的指针不能直接指向它,如上图所示。

这时可以使用GCHandle的Alloc方法,这个方法为指定的对象分配句柄。所支持的句柄有:


[align=left]Normal[/align]
[align=left]此句柄类型表示不透明句柄,这意味着无法通过此句柄解析固定对象的地址。可以使用此类型跟踪对象,并防止它被垃圾回收器回收。当非托管客户端持有对托管对象的唯一引用(从垃圾回收器检测不到该引用)时,此枚举成员很有用。 [/align]


[align=left]Pinned[/align]
[align=left]此句柄类型类似于 Normal,但允许使用固定对象的地址。这将防止垃圾回收器移动对象,因此将降低垃圾回收器的效率。使用 Free方法可尽快释放已分配的句柄。 [/align]


[align=left]Weak[/align]
[align=left]此句柄类型用于跟踪对象,但允许回收该对象。当回收某个对象时,GCHandle 的内容归零。在终结器运行之前,Weak 引用归零,因此即使终结器使该对象复活,Weak 引用仍然是归零的。 [/align]


[align=left]WeakTrackResurrection[/align]
[align=left]该句柄类型类似于 Weak,但如果对象在终结过程中复活,此句柄不归零。 [/align]
其中Pinned句柄就是pin_ptr,由于该内存地址不变,所以该句柄指向的托管内存不进行垃圾回收,可以与指针相互转换。


GCHandle::Alloc(object^ , GCHandleType::Pinned);


Pointer = Marshal::UnsafeAddrOfPinnedArrayElement(object^ );



下面代码使用vs2005的C++/CLI语言进行了试验。首先新建两个数组,并对第一俄数组进行赋值,将该数组转化为指针后,调用IPP的图像处理操作,镜像操作。然后将结果保存在第二个数组中。最后将两个数组显示出来。


array<unsigned char>^ arraybyte = gcnew array<unsigned char>(m_nImageWidth*m_nImageWidth*3);


array<unsigned char>^ arraybyte2 = gcnew array<unsigned char>(m_nImageWidth*m_nImageWidth*3);


int tmp=0;


for(int i=0;i<m_nImageWidth*m_nImageWidth*3-2;i++)




...{


tmp = i%(m_nImageWidth*3);


if(tmp<50 && (i - tmp*m_nImageWidth*3<50*3))




...{


arraybyte[i] = 255;arraybyte[i+1] = 255;arraybyte[i+2] = 255;


}


}






GCHandle handle = GCHandle::Alloc(arraybyte, GCHandleType::Pinned);


IntPtr hundleimg = (IntPtr)Marshal::UnsafeAddrOfPinnedArrayElement(arraybyte,0);




bitmap = gcnew Bitmap(m_nImageWidth,m_nImageWidth,m_nImageWidth*3,PixelFormat::Format24bppRgb,hundleimg);




GCHandle handle2 = GCHandle::Alloc(arraybyte2, GCHandleType::Pinned);


IntPtr hundleimg2 = (IntPtr)Marshal::UnsafeAddrOfPinnedArrayElement(arraybyte2,0);




IppiSize size;


size.width = m_nImageWidth;


size.height = m_nImageWidth;




IppiRect rect;


rect.x = rect.y = 0;


rect.width = rect.height = m_nImageWidth;


ippiMirror_8u_C3R(


(const unsigned char*)hundleimg.ToPointer(),m_nImageWidth*3,


(unsigned char*)hundleimg2.ToPointer(),m_nImageWidth*3,


size,IppiAxis::ippAxsVertical);




newbitmap = gcnew Bitmap(m_nImageWidth,m_nImageWidth,m_nImageWidth*3,PixelFormat::Format24bppRgb,hundleimg2);



在Form1_Paint()方法中绘制两个Bitmap:


Graphics ^g = e->Graphics;


g->DrawImageUnscaled(bitmap,Point(0,0));


g->DrawImageUnscaled(newbitmap,Point(m_nImageWidth+10,0));





以下是输出的结果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: