问题描述
具有以下C#代码,用于加载和卸载C ++ DLL.
Have the following C# code for loading and unloading a C++ DLL.
我只加载DLL一次,但是代码必须卸载DLL 2次.同样,在卸载DLL之后,当我再次加载它并调用DLL的导出函数时,也会收到以下错误消息:
I load DLL only once, but code has to unload DLL 2 times. Also after unloading DLL, when I load it again, and I call DLL's exported function, I get the following error message:
DLL依赖于其他DLL.
DLL depends on other DLLs.
/// //////////////handle of FDD DLL:
System.IntPtr SystemIntPtr_handle_of_DLL=System.IntPtr.Zero;
private void button4_Click(object sender, EventArgs e)
{
try
{
string string_Dependency_path = ".\\DLL_Dependencies\\";
Call_DLL.SetDllDirectory(string_Dependency_path);
SystemIntPtr_handle_of_DLL = Call_DLL.LoadLibrary("DLL.dll");
if (SystemIntPtr_handle_of_DLL == System.IntPtr.Zero) { throw new Exception("DLL did not load"); }
}
catch (Exception Exception_Object) { MessageBox.Show(Exception_Object.Message); }
}
private void button5_Click(object sender, EventArgs e)
{
try
{
int int_FreeLibrary_counter = 0;
while (Call_DLL.FreeLibrary(SystemIntPtr_handle_of_DLL))
{
int_FreeLibrary_counter++;
}
MessageBox.Show("DLL unloaded. You will have to load it again. (Unloaded" + int_FreeLibrary_counter + " times)");
}
catch (Exception Exception_Object) { MessageBox.Show(Exception_Object.Message); }
}
invoke方法:
class Call_DLL
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetDllDirectory(string string_Dependency_path);
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string string_DLL_name);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr IntPtr_handle_of_DLL);
}
编辑
我忘了在加载DLL之后和卸载DLL之前包含调用DLL导出函数的以下内容.可以认为这些导出的函数中正在发生其他事情,这会导致奇怪的行为(即加载1次,必须卸载2次):
EDIT
I forgot to include the following which call DLL exported functions, after loading DLL and before unloading DLL. It makes sense to think that something else is going on inside these exported functions which is causing strange behavior (i.e. loading 1 time, having to unload 2 times):
[DllImport(@"DLL.dll", EntryPoint = "getFreq")]
public static extern System.IntPtr getFreq([In, Out, MarshalAs(UnmanagedType.LPStr)] string char_Address, [In, Out, MarshalAs(UnmanagedType.I4)]int int_Num, [In, Out, MarshalAs(UnmanagedType.I4)]int int_Samp);
[DllImport(@"DLL.dll", EntryPoint = "setNat")]
public static extern System.IntPtr setNat([In, Out, MarshalAs(UnmanagedType.LPStr)]string char_Address_File_nat);
[DllImport(@"DLL.dll", EntryPoint = "getMode")]
public static extern System.IntPtr getMode();
推荐答案
问题的更新提供了足够的信息来解释行为.
The update to your question provides enough information to explain the behaviour.
- 您调用
LoadLibrary
加载占引用之一的DLL. - 您调用
DllImport
p/调用函数,这些函数又导致对LoadLibrary
的调用.那是对库的另一种引用. - 然后,当您调用
FreeLibrary
时,此操作会成功两次,因为有两次调用LoadLibrary
.
- You call
LoadLibrary
to load your DLL which accounts for one of the references. - You call
DllImport
p/invoke functions which in turn lead to a call toLoadLibrary
. That's the other reference to the library. - Then when you call
FreeLibrary
, this succeeds twice since there were two calls toLoadLibrary
.
但是现在您遇到了麻烦,因为您已经落后于p/invoke系统的后台,并且它仍然认为它拥有对DLL的引用之一.您第二次调用FreeLibrary
时从中窃取的引用.
But now you are in trouble because you've gone behind the back of the p/invoke system and it still believes that it owns one of the references to the DLL. A reference that you stole from it with your second call to FreeLibrary
.
我想您所缺少的信息是DllImport
p/调用如何绑定到该函数的方式.您希望他们可以通过调用GetModuleHandle
获得模块句柄.他们没有.他们称LoadLibrary
.他们是在第一次调用它们时执行此操作的,并且加载的模块一直保持加载状态,直到程序集本身卸载为止.
I guess that the information you are missing is how the DllImport
p/invokes bind to the function. You are hoping that they will obtain a module handle by calling GetModuleHandle
. They don't. They call LoadLibrary
. They do this the first time they are called and the module they load stays loaded until the assembly itself unloads.
首先,您要做的就是遵守规则.规则规定,每次对LoadLibrary
的调用都应与对FreeLibrary
的调用相匹配.您调用LoadLibrary
一次.因此,您还必须完全调用一次FreeLibrary
.停止调用两次,一切都很好.
What you have to do, above all else, is follow the rules. The rules state that each call to LoadLibrary
is to be matched by a call to FreeLibrary
. You call LoadLibrary
once. So you must call FreeLibrary
exactly once also. Stop calling it twice and all is well.
我怀疑您实际上是在尝试安排一个可以加载和卸载DLL的系统.这样可以防止您通过DllImport
使用p/调用.您必须使用LoadLibrary
和GetProcAddress
完成所有操作.
I suspect that you are actually trying to arrange a system whereby you can load and unload DLLs. This prevents you from using p/invoke via DllImport
. You'll have to do it all with LoadLibrary
and GetProcAddress
.
您使用的SetDllDirectory
看起来有些混乱.您期望".\\DLL_Dependencies\\"
与什么有关?提供完整的路径.
Your usage of SetDllDirectory
looks somewhat messed up. What do you expect ".\\DLL_Dependencies\\"
to be relative to? Supply a full path.
这篇关于尽管我只做过1次LoadLibrary,但必须做2次FreeLibrary.另外,在卸载DLL之后,尝试再次加载DLL时,会发生错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!