1)P/Invoke
在windows平台下调用dll一般要dll中的方法申明成stdcall,在windows CE下是cdecl,在p/Invoke层中使用的算法如下:
- 将制定的dll加载到进程的地址空间
- 找到所需的函数地址
- 对数据进行列集
- 调用函数
一般p/invoke调用经常出现函数类型和顺序不匹配的bug(调用约定不匹配),都是程序员不细心导致的,不过这个有一个简单的方法,
幸运的是有一个MDA可以简化这个过程,即pInvokeStackImBalance这个MDA可以用来找出特定类型的调用约定不匹配问题,要启用它可以使用以下配置文件。
能不能和非托管代码进行回调操作呢,答案是肯定的,呵呵,看下面的非托管代码
只要加个委托就可以了,呵呵,简单吧。
简单是简单,不过有一个致命的问题,当执行com的回调时候,托管环境的委托已经被回收了,这样就会导致com回调值会去写一个没有内容的内存区域,.net会抛出一个错误。
解决办法还要依靠MDA,callbackOnCollectecDelegate。这个MDA维持了一组已被收集委托的trunk列表,每当调用回调委托时MDA都会查询这个列表,如果发现调用了一个已被回收的委托时就会报一个错误。
强烈建议启用这个MDA,否则要找出由于互操作导致的问题会非常困难。
委托使用的调用约定是stdcall,必须非常小心的确保非托管的回调定义与stdcall调用约定相匹配。
在进程p/invoke调用时还可以启用MDA的调用日志。
2)Com调用
调用com比较复杂,因为它有一套自己的注册,实例化,生命周期管理以及列集的过程,一般会有个代理层
RCW可以复制com的生命周期,当没有引用的时候,引用为0,因而com对象直到GC清除RCW后,才会自己清除自己。
有一种方法可以手动清除com对象,Marshal.ReleaseComObject方法。