用C++/CLI与非托管代码交互比用C#方便多了

时间:2022-09-01 12:21:57
  没有使用C++/CLI之前,我很怀疑它存在的意义.因为C#的语法更清爽,运行效率也不比C++差多少.C++本身就很复杂了,再乘以CLI的复杂度,我不能想出人们为什么会学习它,使用它.
  但是在使用C#的过程中,渐渐发现.Net类库不够丰富,有很多功能必须通过P/Invoke来实现.一般常用的Windows API函数还好说,接口通常比较简单,DllImport + IntPtr已经足够了,而且还有www.pinvoke.net这个很大的资源库,使用起来还是相当方便的. 虽然有时看到那个日渐庞大的NativeMethods类不爽,但是整体来说,能解决问题.
  等到我必须使用第三方C/C++类库时,我发现使用C#与它们交互实在太痛苦了.普通的对整型数的指针,引用这些好说,但是一碰到复杂的(尤其是嵌套的)数据结构,我就发现自己面对着成百上千行的.h不想动手--天哪,我只想调用一个函数,为什么要用C#重写这么些复杂的struct定义?就连最简单最常用的byte[],在托管与非托管代码间传递也要大耗周折.
  在这两天使用Intel JPEG Library(ijl15.dll)时,我终于忍受不了了,于是想到用C++包装一下对它的调用,简化一下传入传出的参数.完成后,对着那个20K的原生dll,想着我还得在C#里弄DllImport之类的东西,终于觉悟了:干吗不用C++/CLI? 虽然对它的了解不是很深(只在05年看过Stan Lippman在<<程序员>>上发表的两篇文章),但是实际做起来真的很爽!
  一个pin_ptr关键字,直接抹去了托管与非托管之间的边界;而且居然能用CopyMemory从原生unsigned char*里往System.Byte[]里拷贝内容!我的天!原来就算像我这样了解得这么少的人,也能从C++/CLI里获得这么大的好处!
  以前因为没有.Net版本而放弃的类库,现在我都可以拿来用了.直到现在我才明白,错过C++/CLI的这些日子里,我错过了多少东西.

附,有C#及C++背景的人使用C++/CLI的必备知识:

1, C++/CLI里的new等于C++里的new, gcnew等于C#里的new
2, 原生指针用*表示,托管引用使用^表示
   如: Stream^ stream = gcnew Stream();
3, array<unsigned char>^ 等于 System.Byte[]
4, pin_ptr关键字能把托管引用转换为原生指针:
   如: pin_ptr<BYTE> pBytes = & byteArray[0];
   然后pBytes就可以当作原生的BYTE* 使用了.
   等代码执行完pBytes的有效范围,byteArray就会恢复可被GC处理的状态.

只需要知道简单的这几点,就可以开始获得C++/CLI带来的巨大便利了!