有一个关于如何在运行时设置DllImport搜索目录的DllImport。用两行代码可以很好地工作。
然而,许多开源项目却使用LoadLibrary函数。有“谣言”说通过委托调用本机方法要慢一些。我称它们为“流言”,因为我只在两个地方看到过这种情况,而且这无论如何都是微观优化。
最有趣的地方是这篇博文:http://ybeernet.blogspot.com/2011/03/techniques-of-calling-unmanaged-code.html
在这里,作者衡量了不同技术的表现:
NNanomsg使用函数委托,但在这条线上提到这篇博客文章时评论道,“这对传统的P/Invoke的性能影响显然不好”。
来自Kestrel服务器的ASP vNext使用了与Libuv库相同的技术:这是代码
我认为使用委托比使用简单的DllImport更麻烦,考虑到性能差异,我想知道为什么面向性能的库使用委托而不是设置dll搜索文件夹?
是否有任何技术上的原因,如安全性,灵活性或其他-或这只是一个品味的问题?我不明白这个理由--难道作者没有搜索StackOverflow就足够了吗?
发布于 2015-01-16 11:28:14
Hmya,博客文章,这种根本上有缺陷的技术信息分发方式。如果我们能投票给他们,世界就会变得更好。作者在比较苹果和橙子。更像是苹果和自行车。
这里有两种根本不同的互操作场景。第一个是“正常”程序,它是一个在非托管DLL中调用代码的托管程序。使用DllImport属性或C++/CLI是首选的武器。在CLR内部非常优化,它动态地生成机器代码来转换参数并进行调用。重要的是,托管程序总是运行大量的非托管代码,因为它运行在纯非托管操作系统之上。
你所说的“慢”版本,正朝着相反的方向发展。从非托管程序调用托管代码。有些人称其为“反向调用”。这要复杂得多,因为在调用托管代码之前,首先必须加载并初始化CLR。并创建一个应用程序域。并找到并加载包含代码的.NET程序集。JIT编译它。
有三种基本方法可以做到这一点:
[ComVisible(true)]属性,将它们公开为COM组件。非常简单,非托管代码完全不知道它实际上使用的是.NET代码。默认的CLR主机被加载,COM组件的注册表条目指向mscoree.dll,它在必要时引导CLR。唯一的缺点是非托管代码作者需要编写COM客户端代码,这一技能正在消失。第三种方式有很大的缺点,超出了通话的费用。它的扩展性很差,每个方法都必须显式地导出,并且必须是静态的,因此不能实现对象模型。和超级骗子,可怕,肮脏,不可能处理的问题,你无法得到任何诊断时,电话失败。托管代码喜欢抛出异常,如果不是来自代码本身,则从试图告诉您传递错误参数或无法准备代码的CLR中抛出异常。您看不到这些异常,因此无法判断函数是否失败,也无法说明其失败的原因。如果非托管代码没有捕捉到带有非标准__try/_关键字,那么程序就会爆炸。没有任何诊断。即使它确实捕捉到SEH,你也只能得到一个“它不起作用”的信号。
必须编写以这种方式调用的托管代码来处理此问题。它必须包含所有公共方法中的尝试/捕获它们。并记录异常,并提供一种返回错误代码的方法,以便调用方能够检测故障。但是,严重的问题,如缺少依赖all或版本控制问题,根本无法诊断。对于非托管代码作者,简单的LoadLibrary + GetProcAddress来说,这看起来很容易,然而,这是一个长期的支持噩梦。
https://stackoverflow.com/questions/27981719
复制相似问题