P/Invoke 和非托管 DLL 状态
我有一个程序集和一个非托管 DLL。我尝试在非托管 DLL 中使用静态变量,但它似乎无法在程序集的调用之间保留下来。
我想知道非托管 DLL 中的静态变量是否可以存在于 P/Invoke 调用之间,可能是我遗漏了代码中的某些内容。如果不是,如果全局静态变量不是一个选项,那么存储此类非托管 DLL 状态的最佳方法是什么?
I have an assembly and an unmanaged DLL. I tried to use a static variable in the unmanaged DLL but it does not seem to survive between calls from the assembly.
I wonder whether static variables in unmanaged DLLs can exist between P/Invoke calls, possibly I miss something in my code. If not, what is the best way to store a state for such an unmanaged DLL if a global static variable is not an option?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
.Net 运行时通常不会自行卸载 pinvoke DLL,因为它无法知道这样做是否安全,例如它们是否包含状态,包括静态字符串等全局变量。
您的问题不清楚您是指 .Net 端的 static 还是非托管端的 static/const 。如果您指的是托管端的一个,那么在呼叫返回后,如果它已被整理,并且取决于托管端的呼叫设置,则不能保证它存在,除非您遵循一些非常具体的规则。如果它只是一个计划编号,那么它并不重要,所以我将假设它是一个字符串或其他更复杂的结构。
举个例子,如果被调用者是 dll 中的 ac 函数,需要 ansi 字符串,并且您让 pinvoke 接受 C# 字符串,它会为您将 c# unicode 字符串编组为 asni 字符串,并期望回收该字符串调用完成后的内存,即使该字符串来自 C# 静态。即使情况并非如此,任何指向托管内存的指针在调用后都应被视为无效,除非您固定该内存。
这里有一些绳索上吊自杀:) 小心使用它。这将无限期地锚定托管内存,我不建议这样做。拥有自己的字符串副本的 DLL,或者拥有自己的副本的托管端,都不会是有史以来最大的编程犯罪。实际上,如果它们每个人在自己的堆中都有一个,如果它确实是静态的,那么速度会快得多。 C 函数需要在调用返回之前创建自己的副本。
The .Net runtime will typically not unload your pinvoke DLLs on its own, as it has no way of knowing if its safe to do so, like if they contain state, including and globals like static strings or whatever.
Its not clear in you question wether you mean a static on the .Net side or a static / const on the unmanaged side. If you mean one on the managed side, then its not guarenteed to exist after the call comes back, if its been marshaled, and depending on the setup for the call on the managed side unless you follow some very specific rules. If its just a plan number then it doesnt matter so I'm going to assume its a string or someother more complex structure.
As an example, if the callee is a c function in a dll that expects a ansi string, and you let pinvoke take a C# string, it will marshal the c# unicode string to an asni string for you, and will expect to get to reclaim that memory after the call is done, even if that string came from a C# static. Even if that wasnt the case, any pointer to managed memory should be considered invalid after the call unless you are pinning that memory.
Here is some rope to hang yourself :) Use this with care. This will anchor managed memory indefinately, and I woulodnt suggest doing this. The DLL having its own copy of a string, or managed side having its own copy, wouldnt be the greatest programming crime ever committed. And as a practical matter would be much faster if they each have one in thier own heap, if it is indeed intended to be static. The C function needs to make its own copy before the call returns.
这种状态完全取决于所讨论的非托管代码,这取决于它对静态变量的处理方式,一旦调用它,您就无法控制它并受到所讨论的库的规则的约束。
一位评论者建议您可以通过卸载包含静态的库来删除静态,这在所有情况下都是不可能的(您无法卸载主 c 库),但可能对您有用。
This kind of state depends entirely on the unmanaged code in question, it is up to that what it does with it's static variables, once you call into it, you have no control over it and are bound by the rules of the library in question.
One commenter suggests you can remove a static by unloading the library that contains it, this isn't possible in all cases ( you can't unload the main c library ) but may work for you.