开发人员应该了解与托管代码的互操作性

时间:2010-12-03 12:31:28

标签: c# c++ pinvoke

作为C#开发人员,我认为我们中的许多人都有从托管代码调用非托管代码的经验。

在处理托管代码和非托管代码之间的互操作性时,您遇到过的最困难的问题是什么? (您最好提供代码示例,如C ++函数签名和C#包装器)

如何调试运行时错误,因为visual studio在处理调用时没有提供高级调试信息?

2 个答案:

答案 0 :(得分:4)

一般而言,如果您对C的了解不足以找到正确的声明,那么很难找到P / Invoke声明的权威参考。互联网上有很多不好的声明。典型的陷阱是VB6声明,其中有 lot ,其中真正为int的参数声明为Long。 Long是VB6中的32位整数类型,由于历史原因,Integer是16位。

另一个广泛的错误是使用int,其中需要IntPtr。这些声明在32位模式下工作正常但在64位模式下行为不正常。特别麻烦的是带有4个或更少参数的函数,错误的参数类型不会生成PInvokeStackImbalance MDA警告,因为前4个函数参数在CPU寄存器中传递。在作者宣布完成工作后很长时间内,这个漏洞很容易咬人,很难再回到它并诊断出麻烦。

下一个麻烦是声明和维护P / Invoke声明或C ++ / CLI包装器的单调乏味。当非托管API很大时,你最终会写出很多它们。当你明白错误时,他们每个人都准备好给你一个难以诊断的运行时错误。

真正的硬件互操作是使用基于IUnknown的接口的COM服务器。此类服务器没有类型库,因此没有机会使用Tlbimp.exe自动生成互操作库。您必须在C#代码中重新声明接口,并确保获得[Guid]和方法声明正确。当接口继承自基于IUnknown的中间接口时,缺乏对多重继承的支持需要跳过额外的箍。 this author错误地称之为“继承税”的问题。

这种服务器更常见,然后才能满足需求。几乎所有你想用shell做的事(explorer.exe)都是以IUnknown为例。 Vista和Win7扩展也是如此,它们完全由Windows API Code Pack btw包装。

是的,错误处理。太多的非托管代码,只返回一个不友好的错误代码,如E_FAIL或E_UNEXPECTED。并且没有实现IErrorInfo所以你得到的是一个无用的通用消息。或者返回BOOL以指示失败的API,邀请程序员简单地忽略返回值。和AccessViolation或致命的引擎执行错误,非托管代码在你的脸上爆炸,没有任何面包屑,以找出问题所在。这对C#interop并不特别,这样的代码很难让任何人使用。

除此之外,它通常很简单。 .NET中的P / Invoke编组和COM互操作支持非常出色,并且明显优于其他虚拟机中可用的。

答案 1 :(得分:0)

引用计数框架:虽然CLR可以垃圾收集它不再使用的所有内存,但它知道非托管库中的内存的zip。因此,您需要手动释放从非托管源获取的资源。