Reputation: 5124
I'm trying to unload a C++ DLL from my C# program and then reload it and useits functions. for the unloading part i Used this answer: Unload a DLL loaded using DllImport
In order to reload it I used the LoadLibrary function. This is my code:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
internal class Program
{
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("TestLibrary.dll", SetLastError = true)]
private static extern int GetValue();
private static void Main(string[] args)
{
int val = GetValue();
IntPtr p2 = LoadLibrary("TestLibrary.dll");
bool isFree = FreeLibrary(p2);
isFree = FreeLibrary(p2);
p2 = LoadLibrary("TestLibrary.dll");
val = GetValue();
}
}
}
The weird thing is that pinvoke still works when I reload the module.
Isn't the module supposed to be loaded to a different part of the memory?
Can I do it the way I did or am I going to have trouble with it?
Upvotes: 2
Views: 1345
Reputation: 613461
When you unload and reload a module it might load at a different address. Or it might load at the same address. It's up to the system to decide where to load the module. When you reload you will need to call GetProcAddress
again for each function that you import, because the addresses of the functions may have changed, if the module has loaded at a different address.
Of course that part is missing from your code altogether. The part where you call GetProcAddress
for every function that you import. You have to do it that way if you want to be able to reload. Otherwise the module might load at a different address and then everything falls over, as explained at the topic you linked to.
It looks as though you have been unlucky and the module is re-loaded at the same address. I say unlucky because you have not been able to observe the failure mode, and so are erroneously tempted into believing that your code is correct.
So you have to stop p/invoking directly to the module and obtain all function pointers by calling GetProcAddress
. Convert these to delegates with Marshal.GetDelegateForFunctionPointer
.
Upvotes: 5