Unload a DLL loaded using DllImport - c#

How do I unload a DLL which has been loaded using DllImport in C#?

The most reliable way to unload an unmanaged DLL from a process that got loaded by a [DllImport] pinvoke declaration is to load it yourself, again, by pinvoking LoadLibrary(). That gives you a reliable handle to the DLL and works correctly even if the module name of the DLL is ambiguous. It doesn't have any affect at runtime, other than the Windows loader increasing the internal reference count on the DLL from 1 to 2.
You can then pinvoke FreeLibrary() twice to decrease the reference count to 0, passing it the IntPtr you got from LoadLibrary(). That unloads the DLL, as well as any dependent DLLs that got loaded.
Beware that you'll get very nasty failure when you try to pinvoke any exported function on the DLL again, any time after doing this. The pinvoke marshaller is unaware that the DLL isn't around anymore and will call the function at the address it thinks is still valid. Which bombs your program with an AccessViolation exception if you are lucky. Or runs a completely random bit of code if you are not so lucky and the address space formerly occupied by the DLL got re-used by another DLL. Anything can happen then, none of it good.

This should free a module previously loaded when you called P/Invoke function.
[DllImport("kernel32", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);
public static void UnloadModule(string moduleName)
{
foreach(ProcessModule mod in Process.GetCurrentProcess().Modules)
{
if(mod.ModuleName == moduleName)
{
FreeLibrary(mod.BaseAddress);
}
}
}

Based on Peters recommendation this works for me:
[DllImport("kernel32", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);
public static void UnloadImportedDll(string DllPath)
{
foreach (System.Diagnostics.ProcessModule mod in System.Diagnostics.Process.GetCurrentProcess().Modules)
{
if (mod.FileName == DllPath)
{
FreeLibrary(mod.BaseAddress);
}
}
}

Late to the party, but I've made a tool to do this. It's supposed to run in Unity, but I think it can be adopted to other C# solutions. It's available here: https://github.com/mcpiroman/UnityNativeTool.
Please note that it is essentionally a hack (but often used hack, see Harmony), so I don't quite recommend using it at production code.

Since I came across the information here while I was looking around for information I figure I will contribute back what I ended up doing to fix an issue with the Sixense SDK on OSX IN UNITY. You'll see in there an implementation of dynamically loading/unloading a dylib on OSX:
https://gist.github.com/amirebrahimi/d7b02c01bcd3ca7da144

Related

Differences in methods to call unmanaged C++ dll from C#

I am calling some unmanaged C functions (in an external dll) from C#. I have 2 different methods to do so, and I am not sure of the differences between the 2 (other than the amount of code)
Method #1
[DllImport("PComm32.dll",CallingConvention=CallingConvention.StdCall, EntryPoint ="PmacSelect")]
public static extern int PmacSelect(IntPtr intPtr);
int device = PmacSelect(IntPrt.Zero);
Method #2
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int PmacSelect(IntPrt intptr);
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
public PmacSelect PmacSelectFunction;
private IntPtr pDll = LoadLibrary("PComm32");
IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "PmacSelect"); //find the function in the loaded pcomm32 dll
PmacSelectFunction = (PmacSelect)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,type(PmacSelect));
int device = PmacSelectFunction(IntPrt.Zero);
Both methods work, and call the PmacSelect Function located in the PComm32.dll file.
My question is what are the functional differences between the 2 methods?
Method #1 must rely on windows managing the DLL in the background for me as needed? Could windows load and unload the dll without my knowledge? I dont really care if it does, as long as it automatically loads is when I call a function in the dll.
Method #2 The DLL is loaded explicitly when I call LoadLibrary. Does the library remain in memory until I free it?
I'll give you answers, but you seem to already understand what is going on.
My question is what are the functional differences between the 2 methods?
There is no functional difference between the two methods. In the first method (which you should use if at all possible), the DotNet framework is handling everything for you. Under the hood, it is doing exactly what you're doing manually: Calling LoadLibrary, GetProcAddress, and at some point, FreeLibrary. Those are the steps to calling a function in a DLL.
Method #1 must rely on windows managing the DLL in the background for me as needed? Could windows load and unload the dll without my knowledge?
Yes, that's exactly right, although I wouldn't say it is without your knowledge. You are telling it to do that when you write [DllImport("PComm32.dll"...)].
Method #2 The DLL is loaded explicitly when I call LoadLibrary. Does the library remain in memory until I free it?
Again, yes, you understand what is happening.
Since you seem to answered your own questions and I've merely confirmed your answers, let you give you the reasons why you should (almost) always use #1:
It works just as well
It is easier to use and easier to read / maintain
There is no value in doing it the hard way (#2)
I can only think of one reason that you would ever want to bother with the second method: If you needed to be able to replace the DLL, on the fly, with a newer version or something, without quitting your application, then you would want the fine grain control over when the DLL is unloaded (so that the file can be replaced).
That is unlikely to be a requirement except in very special cases.
Bottom Line: If you're using C#, you accept the fact that you are giving control to the framework in exchange for being able to focus on the work, and not worry about things like DLL or memory management. The DotNet framework is your friend, let it do the heavy lifting for you, and focus your efforts on the rest of the code.
When you pinvoke with DllImport, LoadLibrary ends up getting called for you, and the exported function is (hopefully) found in the EAT. Basically in your second example you're doing the same thing as a typedef + GetModuleHandle & GetProcAddress for c/c++.
The only reason I could think to use your second method, would be if the DllMain of your unmanaged module executes code upon attachment to a process, which you might depending on the scenario want to have specific timing control over when that module gets loaded into your process.

How to free memory allocated in C# to an IntPtr passed from C++ dll?

A pointer is passed to me from a C++ dll as followed:
[DllImport("myfile.dll", EntryPoint = "LoadFile", SetLastError = true, CharSet = CharSet.None)]
public static extern IntPtr dLoadFile(string x);
IntPtr p = dLoadFile("myfile");
//Do things with p.
Marshal.FreeHGlobal(p) //crash on this line with exception below.
System.Runtime.InteropServices.COMException: 'One or more arguments
are invalid (Exception from HRESULT: 0x80000003)'
Should I free the memory allocated to IntPtr ? And if yes, how to do it properly ?
Obviously it seems that Marshal.FreeHGlobal() is not the way to go...
Thanks
The general rule is that "who allocates the resources needs to be called to perform the cleanup". In c#, you d not own the memory : the clr owns it. Your shared c# assemblies also share the clr, therfore you have the impression to create an object in one assembly and free it in another. When performing interoperability, a resource created by a library should be cleaned up by the same library via an additional exported api. There are some exceptions though, and they regard when operating systems objects are created :according to the specific documentation of the object in question, you can free the resource at caller site.
In your case, you should export the appropriate api in my file.dll that properly perform the cleanup.
This rule allows you not to disclose internal details, thus allowing you to change your internals without breaking the caller.

Value of static variable in native library between calls from managed library

I have managed web application (WCF service running from IIS, FWIW) written in c#. In certain situations, it performs calls to functions from unmanaged c/c++ library.
Inside the unmanaged library I have some global static variable.
I see that some of the times the value of this variable changes to its initial value between the calls while I would expect it to keep its value always.
The structure is something like this:
Managed.cs
public class Managed
{
[DllImport("native.dll", EntryPoint = "?MyFunc##YGXXZ", ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
static extern void MyFunc();
public void MyWrapper()
{
MyFunc();
}
}
}
Native.cpp
static int counter = -1;
__declspec(dllexport) void __stdcall MyFunc()
{
counter++; // sometimes when I enter this function the counter drops to -1
}
My question is: Does it work as supposed to? Am I missing something? How can I "remember" the value of the variable between the calls?
EDIT: Actually I have 2 web applications running in the same application pool in IIS. So it looks like these 2 applications while running in the same IIS working process, each one loads different instance of my DLL. So the static variables in these two instances are unrelated. Now my (updated) question is: how can I make these 2 applications share the instance of native DLL? And also - how can it be that the same worker process has 2 copies of DLL loaded simultaneously?
After some research I found that the problem was with multiple web applications running from the same application pool. Though IIS uses the same working process for all of the applications, it looks like somehow it creates different copies of unmanaged dlls for each application with different handles and different sets of static variables. That's why they were re-initialized.

Set processor affinity for current thread on Mono (Linux)

I'm writing a custom task scheduler, and I would like to know if there is any way of setting the processor affinity for the current thread on Mono (running on Linux).
For the .NET runtime running on Windows, I've managed to get this to work by following Lenard Gunda's Running .NET threads on selected processor cores article; however, his approach fails on Mono (and Linux) because:
It requires a P/Invoke call to GetCurrentThreadId in the Kernel32.dll library.
The Process.Threads property currently returns an empty collection on Mono.
Does anyone please have a workaround for this?
lupus's answer was on the right track, but it took me some further research to get this implemented (such as the P/Invoke signature for sched_setaffinity and the resolution of libc.so.6). Here's the working code (excluding error-handling) in case anyone needs it:
[DllImport("libc.so.6", SetLastError=true)]
private static extern int sched_setaffinity(int pid, IntPtr cpusetsize,
ref ulong cpuset);
private static void SetAffinity(int processorID)
{
ulong processorMask = 1UL << processorID;
sched_setaffinity(0, new IntPtr(sizeof(ulong)), ref processorMask);
}
Edit: The above signature worked fine for my experiments, but refer to David Heffernan's answer (under my other question) for a suggested correction.
Note that you don't really have control of when a task gets run, that is up to the kernel.
Anyway, on Linux you will need to P/Invoke to sched_setaffinity() to bind a thread to a specific cpu.
See man sched_setaffinity for the interface.

Performance of Calling Unmanaged .dll from C#

How long is the typical overhead added by calling a .dll written in C++ from a C# application using the following syntax?
[DllImport("abc.dll", EntryPoint = "xcFoo", CallingConvention = CallingConvention.Cdecl)]
public extern static Result Foo(out IntPtr session,
[MarshalAs(UnmanagedType.FunctionPtr)]ObjectCallback callback,
UInt64 turnKey,
string serverAddress,
string userId,
string password);
Is there a more efficient way to do it?
Check out this article on how to improve interop performance. What to do and what best to avoid.
http://msdn.microsoft.com/en-us/library/ms998551.aspx
Are you talking about the overhead of invoking the native method? If so, I dont think it is significant at all, as there are a lot of such calls in the .NET framework class libraries.
Now, whether the overhead is significant for your scenario can only be answered by doing performance measurements, and comparing them against what you expect.
The marshalling into the native method will cost three memory allocations from the NT heap, which is not so bad. It's the delegate back that gets worrysome.
A good method to check this sort of thing is throw in a break point where you make calls. Don't know when the library is loaded, so maybe only check the break point on the second call (unless loading cost is your main concern). Then open up the disassembly window in visual studio and see how many lines there are before your dll function is being invoked.
i know this question is old but ive managed to call native functions blazingly fast with not only using calli CIL instruction but also with special trick, but ofc you need to handle pinnig and/or marshalling arguments yourself if you deal with complex types including strings..

Categories

Resources