随笔 - 55, 评论 - 292, 引用 - 17

导航

关于

我是新人,: )

每月存档

最新留言

  • re:Last day at Microsoft
    写的真好,看了觉得很受到启发,谢谢,
    by Zheying Zheng(匿名) on 2010/2/4 10:35:20
  • re:REST API的身份验证(Authentication)
    <p>顶</p>
    by kekesoft(注册) on 2010/1/27 20:27:43
  • re:Last day at Microsoft
    祝你好运啊
    by Eric v(匿名) on 2010/1/24 1:53:34
  • re:Last day at Microsoft
    鄙人正在打算内部调动,跨过欢德福卡海峡去西雅图呢, 以后互通有无,常联系.
    by Charlie 木匠(匿名) on 2010/1/11 4:23:23
  • re:Last day at Microsoft
    Good luck, buddy.
    by Huimiao Liu(匿名) on 2010/1/10 20:18:24
  • re:Last day at Microsoft
    &lt;p&gt;Oops,you are right. 改正了。&lt;/p&gt;
    by demonfox(匿名) on 2010/1/10 18:22:13
  • re:Last day at Microsoft
    2006年8月14日起至2009年1月8日止 是2010年吧
    by q(匿名) on 2010/1/10 14:59:53
  • re:Last day at Microsoft
    &quot;永远选择你最感兴趣的项目而不是升职空间等所谓的职业发展前景&quot; -- 说的很好!Good luck!
    by CoderZh(匿名) on 2010/1/8 20:49:26
  • re:Chrome OS和Android的背后
    Google当然不是在传统的操作系统上去跟微软计算,手机操作系统,Windows CE是公认的烂,Google在这里竞争没有什么不可以。Chrome OS更多的是Google云计算战略的一部分,人家根...
    by 啊(匿名) on 2009/12/22 13:14:12
  • re:利用Powershell做简单的单元测试
    <p>@ grapef: 调用所测试的类的函数的时候当然是通过reflection的,不过这里问题的关键是我无法将assembly加载到一个新的AppDomain中(以便之后可以卸载),如...
    by demonfox(注册) on 2009/10/12 4:55:22
  • re:利用Powershell做简单的单元测试
    我不确定这个是不是PowerShell的问题。但是,你的跨域操作的实现似乎有点问题。 一般情况下,如果需要将Assembly加载到另一个AppDomain中,并调用其中的代码。我都需要有一个两个域都...
    by Colin Han(匿名) on 2009/10/10 23:23:34
  • re:利用Powershell做简单的单元测试
    用powershell每次创建测试代码执行程序的进程,通过解析进程的output来验证成功或失败否。 这样可以避免程序及加载到powershell本身程序域的问题。
    by geniusleft(匿名) on 2009/10/10 12:28:14
  • re:利用Powershell做简单的单元测试
    用reflection调用可以么?
    by grapef(匿名) on 2009/10/10 11:16:34
  • re:为什么要goto? 为什么不要goto?
    呵呵,忘了留下邮件地址了,hiverdarcytutu@sina.com,谢谢啦~ 这个名字的出处正是&lt;傲慢与偏见&gt;呢,那是我最喜欢的一本小说。
    by Darcy(匿名) on 2009/9/14 10:02:28
  • re:为什么要goto? 为什么不要goto?
    <p>@ Darcy: 呵呵,那你也得留给我email呀,: ) 我可以试着找找,也许还能找到。另:我喜欢《傲慢与偏见》,不知你的nickname是否与之有关,: )</p>
    by demonfox(注册) on 2009/9/9 17:04:18

广告

 

 

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空项目:

image

记得调整配置的类型:

image

然后编写如下的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:暂无标签

留言反馈

#re:托管代码 (managed code)和非托管代码 (native code) 的互操作性 (interoperability) – Part I 编辑

@ huangjizhou: Oops, sorry, 我一直都没有注意到你这条留言,抱歉。这样吧,我也打算快点把下篇歇了,那时候再给你广告一下,如何?

@ AlphaWu: 多谢,呵呵。

2009-09-09 17:01:52 | [博主:demonfox]
#re:托管代码 (managed code)和非托管代码 (native code) 的互操作性 (interoperability) – Part I 编辑
写的很不错。
2009-09-02 15:52:16 | [匿名:吴鹏(AlphaWu)]
#re:托管代码 (managed code)和非托管代码 (native code) 的互操作性 (interoperability) – Part I 编辑
这我太熟了,吃过想当相当多的亏。 你要需要顾问,找我好了。
2009-07-31 18:48:03 | [匿名:ablmf]
#re:托管代码 (managed code)和非托管代码 (native code) 的互操作性 (interoperability) – Part I 编辑

您好!您总结的挺好,非常棒!

我和微软亚洲研究院的崔晓源合写的书《精通.NET互操作:P/Invoke,C++ Interop和COM Interop》,也对.NET互操作的技术做了总结,能否在博文中加一下链接,非常感谢。我们书的网站:http://interop123.com/

2009-07-03 21:39:32 | huangjizhou
#re:托管代码 (managed code)和非托管代码 (native code) 的互操作性 (interoperability) – Part I 编辑

个人认为比较好用的,还是CLI

2009-07-03 11:10:23 | rise.worlds

发表留言

标题
姓名
邮件
主页
留言 

Powered by: Joycode.MVC引擎 0.5.2.0