zoukankan      html  css  js  c++  java
  • c#——IntPtr

    c#中无法将类型“int”隐式转换为“System.IntPtr”

    这个是我引用了一个api函数时出现的问题,我在声明中把intptr换成了int还是不可以,这是为什么呢?要如何处理呢?
     
    答:
    您好,C#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄。
    资源的大小取决于使用的硬件和操作系统,但其大小总是足以包含系统的指针(因此也可以包含资源的名称)。

    所以,在您调用的API函数中一定有类似窗体句柄这样的参数,那么当您声明这个函数时,您应该将它显式地声明为IntPtr类型。

    例如,在一个C#程序中调用Win32API mciSendString函数控制光盘驱动器,这个函数的函数原型是:

    MCIERROR mciSendString(

    LPCTSTR lpszCommand,
    LPTSTR lpszReturnString,
    UINT cchReturn,
    HANDLE hwndCallback
    );

    首先在C#中声明这个函数:
    [DllImport("winmm.dll")]
    private static extern long mciSendString(string a,string b,uint c,IntPtr d);

    然后用这样的方法调用:
    mciSendString("set cdaudio door open", null, 0, this.Handle);

    您也可以使用IntPtr.Zero将句柄设置为0;
    或者使用类型强制转换:
    mciSendString("set cdaudio door open", null, 0, (IntPtr)0 );

    或者,使用IntPtr构造函数:
    IntPtr a = new IntPtr(2121);


    这里有两点比较重要:
    一是在C#中声明Win32API时,一定要按照WinAPI的原型来声明,不要改变它的数据类型;
    二是尽量不要过多使用类型强制转换或构造函数的方式初始化一个IntPtr类型的变量,这样会使程序变得难于理解并容易出错。

    希望这些信息对您有帮助。
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    本文章已收录于:
     
    • 近来研究指针,在C#中谈指针,就不得不谈IntPtr,以下是我对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.

    二:用在什么地方

    (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);//将结构体放到这个空间中

  • 相关阅读:
    练习10.9-2
    [转]JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )
    JAVA成员变量为什么不能在类体中先定义后赋值
    core image几个滤镜样例 oc版本号和swift版本号
    UVa 11997 K Smallest Sums 优先队列&&打有序表&&归并
    Android基础新手教程——4.4.1 ContentProvider初探
    Restore IP Addresses -- LeetCode
    Android中Intent传递类对象的方法一(Serializable)
    Effective C++:条款22:将成员变量声明为private
    javascript cookie
  • 原文地址:https://www.cnblogs.com/eve612/p/14445572.html
Copyright © 2011-2022 走看看