x


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_);
     }
 }
 }

more ▼

asked Jul 31, 2012 at 10:01 PM

Jerdak gravatar image

Jerdak
201 23 24 24

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 Modules list was empty for some reason.

Jun 05, 2013 at 08:20 PM AshMcConnell

:( 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) Might save you some time?

Jun 05, 2013 at 09:05 PM Jerdak

Thanks for the reply. If it's possible, would you mind sharing the pre-processing code? No problem if you would rather not, but it might save me some time

Jun 05, 2013 at 09:07 PM AshMcConnell

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.

Jun 06, 2013 at 06:16 AM Jerdak

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 mind-twisting regular expressions, I'll see what can be done :). Thanks for taking the time!

Jun 06, 2013 at 08:38 AM AshMcConnell
(comments are locked)
10|3000 characters needed characters left

0 answers: sort oldest
Be the first one to answer this question
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x4996
x2829
x394
x28

asked: Jul 31, 2012 at 10:01 PM

Seen: 3030 times

Last Updated: Jun 06, 2013 at 08:05 PM