有一个关于如何在运行时为great answer on SO设置搜索目录的DllImport
。使用两行代码可以正常工作。
但是,许多开源项目改为使用LoadLibrary函数。有传言称通过委托调用本机方法的速度较慢。我把它们称为“谣言”,因为我只在两个地方看过这个,这无论如何都是微观优化。
最有趣的地方是这篇博文:http://ybeernet.blogspot.com/2011/03/techniques-of-calling-unmanaged-code.html
在那里,作者测量了不同技术的表现:
NNanomsg使用功能代表,但在this line上提到评论“这对传统P / Invoke的性能影响显然不好”的博客文章。
来自MSFT的ASP vNext的Kestrel server使用与Libuv库相同的技术:here is the code
我认为代理使用比简单的DllImport更麻烦,并且考虑到性能差异,我想知道为什么面向性能的库使用委托代替设置dll搜索文件夹?
是否有任何技术原因,如安全性,灵活性或其他 - 或者这仅仅是品味问题?我不明白其基本原理 - 作者是否可能没有足够的搜索StackOverflow!?
Hmya,博客文章,从根本上证明了分发技术信息的方式。如果我们能投票支持,世界将会变得更加美好。作者正在比较苹果和橘子。好吧,更像是苹果和自行车。
这里比较了两种根本不同的互操作方案。第一个是“普通”的,一个托管程序在非托管DLL中调用代码。使用[DllImport]属性或C ++ / CLI是首选武器。在CLR内部进行了高度优化,它动态生成机器代码,用于转换参数并进行调用。重要的是,托管程序总是运行大量非托管代码,因为它运行在纯粹的非托管操作系统之上。
你在说什么,“慢”版本,正在走另一条路。从非托管程序调用托管代码。有人称之为“反向pinvoke”。它更复杂,因为在您调用托管代码之前,首先必须加载并初始化CLR。并创建一个appdomain。并找到并加载包含代码的.NET程序集。 JIT编译它。
有三种基本方法可以做到这一点:
[ComVisible(true)]
属性,将.NET类公开为COM组件。非常简单,非托管代码完全没有意识到它实际上正在使用.NET代码。加载默认CLR主机,COM组件的注册表项指向mscoree.dll,mscoree.dll根据需要引导CLR。唯一的缺点是非托管代码作者需要编写COM客户端代码,这是一种迷失的技能。第三种方式有很大的缺点,超出了通话费用。它扩展性很差,必须显式导出每个方法,并且它必须是静态的,因此您无法实现对象模型。而这种超级糟糕,可怕,令人讨厌,不可能解决的问题是,当呼叫失败时,你无法获得任何诊断。托管代码喜欢抛出异常,如果不是来自代码本身,那么就是试图告诉您传递错误参数或无法准备代码的CLR。您无法看到这些异常,无法判断函数是否失败,也无法告诉失败的原因。如果非托管代码没有捕获具有非标准__try / __除关键字的SEH异常,则程序会发生炸弹。没有任何诊断。即使它确实赶上了SEH,你也只会得到一个“它没有工作”的信号。
必须编写以这种方式调用的托管代码来处理此问题。它必须在public方法中包含try / catch-em-all。并记录异常并提供返回错误代码的方法,以便调用者可以检测到故障。然而,遗漏的依赖DLL或版本问题等严重问题根本无法诊断。对于非托管代码作者来说,简单的LoadLibrary + GetProcAddress看起来很容易,但它却是一个长期的支持噩梦。