今天心血来潮,想搞搞那个叫“P/Invoke”的东西。听说这玩意儿能让C#和C++勾搭上,实现一些骚操作,咱也来试试水。
先摸清楚这是个啥
简单来说,就是C#本身搞不定的一些事情,可以找C++写好的“库”来帮忙。这“库”一般就是个DLL文件。但是C#不能直接用,就得靠P/Invoke这个中间人来牵线搭桥。
咋用?
主要就是靠一个叫DllImport
的特性。这玩意儿就像个标签,贴在C#的方法上,告诉程序:“这个方法不是我写的,你去那个DLL文件里找找看!”
咱举个栗子,假如有个C++写的DLL,里面有个加法函数:
- 咱先有个心理准备,这玩意儿可能长得像这样(C++代码):
extern "C" __declspec(dllexport) int Add(int a, int b) {
return a + b;
- 然后,在C#里,咱得这么声明:
using *;
public class MyClass {
[DllImport("*")]
public static extern int Add(int a, int b);
看到没,[DllImport("*")]
这句就是关键!它告诉C#,Add
这个方法在“*”这个文件里。
然后public static extern
这些修饰符也得加上,表示这是个外部方法。
开搞!
我这回是想用P/Invoke来操作USB设备。听起来很高大上,就是调用一些Windows API。
- 找原型:得知道Windows API里那些函数长啥样,参数是返回值是这步挺烦的,得去查微软的文档,或者在网上搜别人整理好的。
- 写声明:找到原型后,就照着上面的例子,在C#里用
DllImport
把这些函数声明一遍。这步比较考验耐心,参数类型啥的一定要对应不然容易出幺蛾子。 - 调用:声明好,就可以像调用普通C#方法一样,直接调用这些Windows API。
遇到的坑
- 类型转换:C++和C#的数据类型不是一一对应的,有些类型得转换一下。比如C++的
HANDLE
,在C#里得用IntPtr
。 - 字符串:C++里的字符串处理起来也挺麻烦的,C#里一般用
StringBuilder
。 - 错误处理:调用Windows API可能会出错,得用
*32Error()
获取错误码,然后根据错误码做相应的处理。这块儿有点麻烦,整得我头都大。
总结
P/Invoke这玩意儿,说白就是个“翻译官”,让C#能听懂C++的话。虽然用起来有点麻烦,但确实能解决一些C#搞不定的问题。这回折腾USB设备,算是入门,以后遇到啥需要跟底层打交道的需求,咱也不怕!
不过还是感觉有点累,下次还是尽量找找有没有现成的C#库,能偷懒就偷懒。
还没有评论,来说两句吧...