【问题标题】:P/Invoke and unmanaged DLL stateP/Invoke 和非托管 DLL 状态
【发布时间】:2011-05-17 11:08:33
【问题描述】:

我有一个程序集和一个非托管 DLL。我尝试在非托管 DLL 中使用静态变量,但它似乎在程序集调用之间无法生存。

我想知道非托管 DLL 中的静态变量是否可以在 P/Invoke 调用之间存在,可能我的代码中遗漏了一些东西。如果没有,如果全局静态变量不是一个选项,那么为这种非托管 DLL 存储状态的最佳方法是什么?

【问题讨论】:

  • 只要不卸载 DLL,静态变量就应该存在。所以这应该有效。你能显示一些代码吗?
  • @Codo 我又检查了一次,现在它工作了,所以我错过了一些东西。很抱歉我发布了这个问题,我很容易相信一个变量在调用之间没有存在。我应该关闭这个问题吗?顺便说一句,非托管 DLL 是否在第一次 pinvoke 期间加载一次并在应用程序存在时卸载?我开始相信 DLL 在 pinvoke 后由 CLR 加载和卸载。
  • 加载和卸载 DLL 相当昂贵。所以我不认为它经常发生。但我不知道它何时真正发生。在 SO 上可能值得另一个问题。
  • herehere 的讨论中看来,本地 dll 在 p/invoke 之后仍保持加载状态。

标签: .net c pinvoke


【解决方案1】:

.Net 运行时通常不会自行卸载您的 pinvoke DLL,因为它无法知道这样做是否安全,例如它们是否包含状态,包括静态字符串等全局变量。

您的问题不清楚您是指.Net 端的静态还是非托管端的静态/常量。如果您的意思是托管端的一个,那么它不能保证在调用返回后存在,如果它被编组,并且取决于托管端的调用设置,除非您遵循一些非常具体的规则。如果它只是一个计划号,那没关系,所以我将假设它是一个字符串或其他更复杂的结构。

例如,如果被调用者是 dll 中的 c 函数,它需要 ansi 字符串,并且您让 pinvoke 获取 C# 字符串,它会为您将 c# unicode 字符串编组为 asni 字符串,并期望得到在调用完成后回收该内存,即使该字符串来自 C# 静态。即使不是这种情况,任何指向托管内存的指针在调用后都应该被视为无效,除非您正在固定该内存。

Here is some rope to hang yourself :) 小心使用。这将无限期地锚定托管内存,我不建议这样做。 DLL 拥有自己的字符串副本,或者托管端拥有自己的副本,这不会是有史以来最大的编程犯罪。实际上,如果他们每个人在自己的堆中都有一个,如果它确实是静态的,那么实际上会快得多。 C 函数需要在调用返回之前制作自己的副本。

【讨论】:

    【解决方案2】:

    这种状态完全取决于有问题的非托管代码,取决于它对静态变量的作用,一旦你调用它,你就无法控制它并且受库规则的约束有问题。

    一位评论者建议您可以通过卸载包含它的库来删除静态,这并非在所有情况下都可行(您无法卸载主 c 库),但可能对您有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 2016-03-15
      • 1970-01-01
      • 2014-04-22
      • 2011-09-13
      • 1970-01-01
      相关资源
      最近更新 更多