- Home /
Easier way to handle unloading dlls?
It is my understanding that Unity will not unload a .dll once 'Preview' has been run, if you use [DllImport]. Following the linked post's suggestions I instead used Kernel.dll to load and unload my dll manually. That part works fine.
The issue is that my code needs to be compatible with Android as well so I can't very well link Kernel.dll to do manual loading and unloading. Once I deploy my app I know I can just use [DllImport] and things will work as expected but I need to retain the manual loading and unloading so that Unity's editor doesn't lock my .dll forcing me to close Unity when I need to recompile my C++ DLL.
The following code is the best way I could think of to handle DLL loading on different systems while still allowing me to dynamically load and unload my DLL. Is there an easier way?:
using System;
using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;
public class Plugin {
// Unity editor doesn't unload dlls after 'preview'
#if UNITY_EDITOR
static class NativeMethods
{
[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);
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr Delegate_New();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int Delegate_GetSize(IntPtr plugin);
// Make sure that delegate instances are identical to the actual method being called
Delegate_New plugin_new;
Delegate_GetSize plugin_getsize;
IntPtr? plugin_dll = null;
void InitializeHooks(){
plugin_dll = NativeMethods.LoadLibrary(@"..\Release\Plugin.DLL");
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(plugin_dll.Value, "plugin_new");
plugin_new = (Delegate_New)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(Delegate_New));
pAddressOfFunctionToCall = NativeMethods.GetProcAddress(plugin_dll.Value, "plugin_getsize");
plugin_getsize = (Delegate_GetSize)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(Delegate_GetSize));
plugin_handle_ = plugin_new();
}
void CloseHooks(){
if(plugin_dll == null){
return;
}
bool result = NativeMethods.FreeLibrary(plugin_dll.Value);
Console.WriteLine(result);
plugin_dll = null;
}
#elif UNITY_ANDROID
[DllImport("unityplugin")]
public static IntPtr plugin_new();
[DllImport("unityplugin")]
public static int plugin_getsize(IntPtr plugin);
void InitializeHooks(){plugin_handle_ = plugin_new();}
void CloseHooks(){}
#else
[DllImport("unityplugin.dll")]
public static IntPtr plugin_new();
[DllImport("unityplugin.dll")]
public static int plugin_getsize(IntPtr plugin);
void InitializeHooks(){plugin_handle_ = plugin_new();}
void CloseHooks(){}
#endif
IntPtr plugin_handle_;
public Plugin(){
Close();
}
/// <summary>
/// Close this instance.
/// </summary>
public void Close(){
CloseHooks();
}
/// <summary>
/// Initialize this instance.
/// </summary>
public void Initialize(){
InitializeHooks();
}
/// <summary>
/// Get size from dll. Right now it'll be 42
/// </summary>
public int Size {
get {
return plugin_getsize(plugin_handle_);
}
}
}
Did you ever find a simpler way? I am about to do quite a bit of native dll coding and would rather not restart Unity every compile :). I will try your cunning pointer way first! I tried: - http://stackoverflow.com/questions/2445536/unload-a-dll-loaded-using-dllimport (2nd answer), but the $$anonymous$$odules list was empty for some reason.
:( I did not. I eased some of the burden by writing pre-processing code that would parse my dll headers for C declarations and spit out the boiler plate code above.
I saw on the forums that someone made a nice tutorial for working in Visual Studio outside of Unity. (Not just using Visual Studio to edit Unity scripts) $$anonymous$$ight save you some time?
Thanks for the reply. If it's possible, would you $$anonymous$$d sharing the pre-processing code? No problem if you would rather not, but it might save me some time
I can't find my code for this project. :( But I did find an unfinished post I started about using abstract syntax trees to extract things like "extern "C" void foo()" from code. Which is really all my original scripts did. Scrape for extern
, copy the method signature, and spit out the boilerplate above.
I polished the post off and threw it up on my site. I'm not sure if you'll find it useful.
Thanks Jerdak, haven't had a play with Clang or Python before, so it might be hard to get going, but looks pretty great. I was thinking of just doing some $$anonymous$$d-twisting regular expressions, I'll see what can be done :). Thanks for taking the time!