C# 中intptr用法

一:什么是IntPtr

先来看看MSDN上说的:用于表示指针或句柄的平台特定类型。这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄、它是一个平台特定类型。对于它的解释,这个哥们写的比较好:It’s a class that wraps a pointer that is used when calling Windows API functions. The underlying pointer may be 32 bit or 64 bit, depending on the platform(它是一个类,它封装了调用WindowsAPI函数时使用的指针。根据平台的不同,底层指针可以是32位,也可以是64位).

二:用在什么地方

(1)C#调用WIN32 API

(2)C#调用C/C++写的DLL(其实和1相同,只是这个一般是我们在和他人合作开发时经常用到)

三:怎样用

例如有一函数原型定义为:DLLDemo_API int __stdcall Inptr_Test (LONG param1, HWND hWnd);那么我们在C#中引用时就要这样写:

 [DllImport("DllPlayer.dll", EntryPoint = "IP_TPS_OpenStream")]
 public static extern int  Inptr_Test (int param1, IntPtr hWnd);

在调用的时候就可以向Inptr_Test 的第二个参数传入某一控件的Handle。这里涉及到C#类型与C++类型的对应关系,网上这种有很多,这里就不再赘述,只谈几个经常用到的和经常出错的。

  (1)一般对于char* ,void*这种可以直接对应IntPtr,比如在C#中,我们经常用string类型,其转换为IntPtr再传给char*,void*等,转换方法为
string txt="test"; Marshal.StringToCoTaskMemAuto(txt);

这里有时会用StringToCoTaskMemAnsi,不过StringToCoTaskMemAuto自动分配内存就可以了。这样就会将txt的内容复制到非托管的内存块中。

(2)对于结构体,比如有一结构体 StructText,将其转换为Intptr,尽量不要直接用Marshal.StructureToPtr,这样很容易出错。可以这样来用:

int size = Marshal.SizeOf(StructText);//获取结构体占用空间大小

IntPtr intptr= Marshal.AllocHGlobal(size);//声明一个同样大小的空间

Marshal.StructureToPtr(StructText, intptr, true);//将结构体放到这个空间中
 // ch:保存图片 | en:Save image
        private void SaveImage(IntPtr pData, MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo,int nIndex)
        {
            if ((3 * stFrameInfo.nFrameLen + 2048) > m_nBufSizeForSaveImage)
            {
                m_nBufSizeForSaveImage = 3 * stFrameInfo.nFrameLen + 2048;
                m_pBufForSaveImage = Marshal.AllocHGlobal((Int32)m_nBufSizeForSaveImage);
            }

            MyCamera.MV_SAVE_IMAGE_PARAM_EX stSaveParam = new MyCamera.MV_SAVE_IMAGE_PARAM_EX();
            stSaveParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp;
            stSaveParam.enPixelType = stFrameInfo.enPixelType;
            stSaveParam.pData = pData;
            stSaveParam.nDataLen = stFrameInfo.nFrameLen;
            stSaveParam.nHeight = stFrameInfo.nHeight;
            stSaveParam.nWidth = stFrameInfo.nWidth;
            stSaveParam.pImageBuffer = m_pBufForSaveImage;
            stSaveParam.nBufferSize = m_nBufSizeForSaveImage;
            //stSaveParam.nJpgQuality = 80;//存Jpeg时有效
            int nRet = m_pMyCamera[nIndex].MV_CC_SaveImageEx_NET(ref stSaveParam);
            if (MyCamera.MV_OK != nRet)
            {
                string temp = "No."  + (nIndex + 1).ToString() + "Device save Failed!";
                ShowErrorMsg(temp,0);
            }
            else
            {
                string[] path = { "image1.bmp", "image2.bmp", "image3.bmp", "image4.bmp" };

                Byte[] bArrBufForSaveImage = new Byte[stSaveParam.nImageLen];
                Marshal.Copy(m_pBufForSaveImage, bArrBufForSaveImage, 0, (Int32)stSaveParam.nImageLen);
                Marshal.Release(m_pBufForSaveImage);

                FileStream file = new FileStream(path[nIndex], FileMode.Create, FileAccess.Write);
                file.Write(bArrBufForSaveImage, 0, (int)stSaveParam.nImageLen);
                file.Close();
                string temp = "No." + (nIndex + 1).ToString() + "Device Save Succeed!";
                ShowErrorMsg(temp,0);
            }
        }

你可能感兴趣的:(C#)