3月份从Windows Live转到Windows Embedded后,越来越多地需要与C/C++相依为命了。以前在C#里写点字符串处理的东西基本不用动什么脑子,现在单单是把两个字符串连起来,就要调用一个有4个参数的API。
最近在做的一个项目顶层的用户界面(UI, User Interface)还是选择用C#/WinForm写了,毕竟再用MFC之类的东西,身心受不了那个摧残。不过底层真正实现功能的API还是必须要用C/C++来写(有很多客观的原因必须如此),所以一个必然需要解决的问题就是如何让用托管代码写成的UI层来调用用非托管代码写成的API层里的函数/类。也不知这样的事大家现在是否还经常需要做,不知会用COM/ATL的还有多少人,不过既然就此做了一些调查,我想还是把结果整理一下,写下来,也许对一些朋友会有用呢。
本文只讨论如何从托管代码调用非托管代码,其实反向操作(非托管代码调用托管代码)也有很多类似的技术,大家可以自己查一下资料。
基本上从托管代码调用非托管代码的函数/类型有一下几类方法:
1. 通过Platform Invoke (P/Invoke)
这个在托管代码需要调用Windows API的时候是很常见的,比如要调用kernel32.dll里的SetDllDirectory这个native API,只要这样做就可以了:
using System.Runtime.Interopservices
public MyClass
{
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool SetDllDirectory(string lpPathName);
...
public static void CallSetDllDirectory(string path)
{
...
SetDllDirectory(path);
...
}
}
利用P/Invoke最大的麻烦可能就在于这个native函数的P/Invoke的签名应该如何申明。最常见的一种方法叫做google,就是你把TheAPIYouWantToCall和P/Invoke这两个关键字放在一起google一把,基本就应该找到了,第一个连接十有八九是来自www.pinvoke.net这个网站。
不过如果你要是说你不喜欢Google怎么办?Google上找不到怎么办?要是Google当掉了怎么办?要是Google因为传播色情信息被封锁了怎么办?当然你可以说:我没有Google我有Bing,那也是可行的。不过其实还有更直接的方法,在2008年1月的MSDN杂志上的CLR Inside Out的专栏里就有这么一篇文章:Marshaling between Managed and Unmanaged Code,其中介绍了P/Invoke Interop Assistant这个工具。你不但可以通过这个工具来查找绝大多数公开的Windows API的P/Invoke的签名,而且也可以用它来产生你自己写的native API的P/Invoke签名,很方便。你可以在这里下载这个工具。
2. 通过C++/CLI wrapper class
这个方法主要是利用Managed C++来写一个封装函数/类,并以此来调用非托管的函数/类,而在另一边,用Managed C++写成的封装类的dll又可以直接被C#等托管代码来调用。
假设你有如下的C++类:
class __declspec(dllexport) NativeClass
{
public:
static void Func(LPTCSTR);
...
};
你可以在Visual Studio中建立一个Visual C++的CLR空项目:
记得调整配置的类型:
然后编写如下的Managed C++类:
public ref class MCppClass
{
public:
static void Func(String^ str)
{
NativeClass::Func((LPTSTR)Marshal::StringToHGlobalUni(str).ToPointer());
}
...
};
编译后生成的dll就可以直接被托管代码调用了。当然,关于托管代码变量和非托管代码变量之间marshaling的问题也是很头疼的,不过这个不是本文的讨论内容。
3. 通过CALLI instruction以及Reflection.Emit直接调用非托管代码
CALLI是Intermediate Language (IL)的一个指令。老实说我也不太清楚这个东东怎么用,只是看有的文章提到说可以如此做,但没有深入地研究一下,有兴趣的同学可以参考一下David Broman的这篇文章。
4. 通过COM interop
这个就留待明天的Part II再讲吧,因为我还想顺带提一下COM里的一些相关内容,篇幅可能有些长,并且时间也不早了…
打印 | 张贴于 2009-07-01 17:11:29 | Tag:暂无标签
留言反馈
@ huangjizhou: Oops, sorry, 我一直都没有注意到你这条留言,抱歉。这样吧,我也打算快点把下篇歇了,那时候再给你广告一下,如何?
@ AlphaWu: 多谢,呵呵。
您好!您总结的挺好,非常棒!
我和微软亚洲研究院的崔晓源合写的书《精通.NET互操作:P/Invoke,C++ Interop和COM Interop》,也对.NET互操作的技术做了总结,能否在博文中加一下链接,非常感谢。我们书的网站:http://interop123.com/。
个人认为比较好用的,还是CLI