谢谢楼上,msdn上我是没搜到对照表的,另外,pinvoke有一个专门的网站,上面有很多的对应,但是pinvoke上面的对应也不是统一的,而且我还下了一个小软件,专门转换pinvoke类型的,好像还是ms自己出的一个。
这两个上面的有些类型在使用过程中,并不是唯一的统一的标准,而是可以采用其他的方式来代替的

解决方案 »

  1.   

    你说的很对。因为API是Native C写的,类型很不完善。说实话,C基本只有一种类型,就是32bit整数。特别是SendMessage这个函数,我们知道,lParam wParam这两个参数根据消息不同含义不同,所以在C#使用,我们经常定义出很多版本,比如有时候让lParam直接是字符串甚至结构体类型,这样更明确,使用更简单。
      

  2.   

    一个优秀的程序员,不仅要编写“正确”的程序,同时要编写更好的程序。好比ArrayList也能完成List<T>的功能,但是我们更倾向选择后者,类型更清晰,意味着调用的明确、代码可读性的提高,更好的编译器检查。你给api传int或者intptr,你就需要自己保证传的类型的正确——比如你可能传了无效的指针。但是如果你用string,那么编译器就阻止你传非字符串(的指针),这不是更好么。
      

  3.   

    先说简单的,如果是Win32的API,那就去pinvoke.net上找,一般都能用。如果是其它的库,可能根据需要自己来确定用什么方式。你主要提了int和string,我先说int,
    因为C/C++那边的int不是定长的,而是“平台”尺寸的,导致32位是32位的int,64位是64位的int,但是C#确定了int是32位的,所以在pinvoke的时候,如果C#这边也用int,那么对64位的c/c++库可能会出问题,这个时候为了同时兼容32位和64位,就可以用IntPtr了,因为它也是变长的(这里IntPtr没有当作指针使用,而是当作一个整型)。DWORD是确定32位的,在C#这边应该用int,用IntPtr的话如果是64位的方式会有问题。string就更复杂一点,因为涉及编码方式(还有比如在COM中非0结尾的string的处理)。默认的string处理通过attribute的设置能支持ansi,平台默认(中文系统就是GB2312或其超集),和Unicode三种编码。对于.net,string内部始终是unicode方式的,但是对于C/C++,本身没有字符串这个类型,就是一串byte。比如C/C++那边需要一个utf8编码的字符串,就没法直接用string传递了,因为默认的情况没法支持utf8编码,这个时候就必须用IntPtr传递了,先把字符串用utf8编码方式转换成字节数组,然后分配非托管内存,把转换后的内容copy过去,然后传递这个非托管内容的指针。当C/C++那边不需要这个字符串了,再释放掉分配的内存。所以对string用IntPtr是最底层的方式,但是也最麻烦。像你说的 char *,那就看这个在C/C++那边到底是做怎么用的。情况也比较多:
    如果不考虑中文,只是最简单的ASCII,那传递的时候就直接用ANSI方式的string,最简单。
    如果考虑中文,但是不考虑在中文平台以外使用,那一般用平台默认方式的string就好了。
    如果考虑中文,还考虑在中文平台以外使用,而C/C++那边要求必须是gb2312的编码,那就只好自己转码用IntPtr方式了。用IntPtr还有个原因是生命周期,大部分情况下pinvoke的时候会自动分配非托管内存,根据需要的编码转换并copy那个string到分配的内存,然后传递这个指针,在pinvoke调用结束后,这个分配的内存会被回收。也就是说如果C/C++那边在调用结束后还需要用这个字符串,要不然自己再copy遍,要不然就是用IntPtr,在托管环境管理这个字符串的生命周期。最后说StringBuilder,这个一般是用来做双向传递的,StringBuilder有内部的buffer内存空间,传递StringBuilder到C/C++那边其实就是直接传递了StringBuilder的buffer地址,这样就支持C/C++直接对这块内存进行修改。我写了半天,其实考虑的情况也有限,具体的情况还是要去看msdn了,其实没有标准的转换方式,只能自己搞明白原理然后根据实际情况来 http://msdn.microsoft.com/en-us/library/zah6xy75(v=vs.110).aspx
      

  4.   

    谢谢上面的回复
    你们写的东西,我都认真的看过了,只不过这两天实在有其他的事情耽搁了,一直没机会上网,所以今天中午才看到。
    其实你们都是一个意思,具体情况要具体分析。caozhy,你说的很对,这种做法的确是在提供SDK的时候的最好做法,用一种约束来减少后期的二次开发错误几率。
    winnowc ,首先感谢你手写这么多····你的意思我明白,win32之前我也用过,只不过这个pinvoke让我有点拿不定主意。通过你们的回复,我看出了一点东西,那就是pinvoke其实对类型的转换并没有那么严格,当c中需要什么类型,我给他一个类似的类型就行了,但是具体的这个类型是不是管用,还是要用过才知道,对吧?