P / Invoke和非托管DLL状态

时间:2011-05-17 11:08:34

标签: .net c pinvoke

我有一个程序集和一个非托管DLL。我试图在非托管DLL中使用静态变量,但它似乎不能在程序集调用之间存活。

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

2 个答案:

答案 0 :(得分:2)

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

你的问题不明确,你的意思是.Net方面的静态或非管理方面的静态/ const。如果你的意思是管理方面的一个,那么在呼叫回来之后,如果它被编组,并且根据管理方的呼叫设置,除非你遵循一些非常具体的规则,否则它不会保证存在。如果它只是一个计划编号,那么它无关紧要,所以我将假设它是一个字符串或另一个更复杂的结构。

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

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

答案 1 :(得分:0)

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

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