一:什么是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);
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;
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);
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);
一:什么是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 platfo
C/C++程序中,最经典的就数指针了,如果对指针没有一定认识,那么C/C++语言的学习深度还不够。因此在一般的C/C++程序开发中使用指针作为参数传递也尤为普遍,我们前面的示例中,使用到的char* 与ByteArray* 都是指针。本节使用C#的IntPtr对接口参数进行定义。
Windows 10
Visual Studio 2017
平台工具集:Visual Studio 201...
C#中的IntPtr类型称之为“平台特定的整数类型”,用于本机资源,例如窗口句柄;
资源的大小取决于使用的硬件和操作系统,即此类型的实例在32位硬件和操作系统中将是32位,在64位硬件和操作系统中将是64位;但其大小总是足以包含系统的指针(因此也可以包含资源的名称)。
在调用API函数时,类似含有窗口句柄参数(HANDLE)的原型函数,应显示地声明为IntPtr类型。
IntPtr类型对多线程操作是安全的。
int 和IntPtr互转:
一:什么是IntPtr
先来看看MSDN上说的:用于表示指针或句柄的平台特定类型。这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄、它是一个平台特定类型。对于它的解释,这个哥们写的比较好:It's a class that
wraps a pointer that i
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections;
public class User32API
INtPtr是什么
C#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄。
资源的大小取决于使用的硬件和操作系统,但其大小总是足以包含系统的指针(因此也可以包含资源的名称)。
所以,调用的API函数中一定有类似窗体句柄这样的参数,那么当您声明这个函数时,您应该将它显式地声明为IntPtr类型。
It’s a class that wraps a pointer that is used when calling Windows API functi
C#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄。资源的大小取决于使用的硬件和操作系统,但其大小总是足以包含系统的指针(因此也可以包含资源的名称)。
所以,在您调用的API函数中一定有类似窗体句柄这样的参数,那么当您声明这个函数时,您应该将它显式地声明为IntPtr类型。
例如,在一个C#程序中调用Win32API mciSendString函数控制光盘驱动
// 导入DLL中的函数
[DllImport("yourDllName.dll")]
public static extern void ProcessFloatArray(IntPtr floatPointer, int length);
static unsafe void Main()
// 创建一个float数组
float[] array = new float[] { 1.0f, 2.0f, 3.0f };
// 分配内存,并将float数组复制到该内存中
IntPtr floatPointer = Marshal.AllocHGlobal(array.Length * sizeof(float));
Marshal.Copy(array, 0, floatPointer, array.Length);
// 调用C++函数
ProcessFloatArray(floatPointer, array.Length);
// 将修改后的内存内容复制回float数组
Marshal.Copy(floatPointer, array, 0, array.Length);
// 释放内存
Marshal.FreeHGlobal(floatPointer);
// 输出结果
foreach (float value in array)
Console.WriteLine(value);
在这个示例中,我们首先使用Marshal类的AllocHGlobal方法分配了一块内存,大小为float数组长度乘以每个float的字节数。然后,我们使用Marshal类的Copy方法将float数组复制到分配的内存中。
接下来,我们调用C++函数,并将分配的内存指针作为参数传递。在C++函数中,你可以通过访问该指针来读取和修改float数组。
最后,我们使用Marshal类的Copy方法将修改后的内存内容复制回float数组,并使用Marshal类的FreeHGlobal方法释放分配的内存。
请注意,由于这涉及到指针操作,所以在Main方法的声明中加入了`unsafe`关键字。此外,这个示例假设你已经有了一个能够接受float*参数的C++函数,并且在调用C++函数之前已经将float数组复制到了分配的内存中。