Skip to content

Single-file helper to allow Unity NativePlugins to be updated without restarting the editor.

License

Notifications You must be signed in to change notification settings

forrestthewoods/fts_unity_native_plugin_reloader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 

Repository files navigation

fts_unity_native_reload

fts_unity_native_reload is a single C# file that helps Unity auto-reload native plugins.

The only file you need is NativePluginLoader.cs. Everything else exists only to provide a complete example.

The Problem

Unity doesn't unload DLLs after using PInvoke. This makes developing Native Plugins a huge pain in the ass. Everytime you want to update the DLL you need to close the Unity Editor or else you get a "file in use" error. This can be very slow and significantly reduces iteration speed.

This project solves that problem with a simple ~200 line file.

Consider the following:

// my_cool_header.h
extern "C" {
    __declspec(dllexport) float sum(float a, float b);
}

The standard way to call this NativePlugin is:

// C#
// Old and busted PInvoke
public static class FooPlugin_PInvoke {
    [DllImport("cpp_example_dll", EntryPoint = "sum")]
    extern static public float sum(float a, float b);
}

My new and improved way:

// C#
// New hotness
[PluginAttr("cpp_example_dll")]
public static class FooPlugin
{
    [PluginFunctionAttr("sum")] 
    public static Sum sum = null;
    public delegate float Sum(float a, float b);
}

void CoolFunc() {
    float s = FooPlugin.sum(1.0, 2.0);
    float t = FooPlugin_PInvoke.sum(1.0, 2.0); // also works
}

Tada! For this to work all you have to do is add the NativePluginLoader script to your scene.

How It Works

NativePluginLoader.Awake scans all assemblies for classes with the PluginAttr attribute. It calls LoadLibrary with the specified plugin name.

Next, it loops over all public static fields with the PluginFunctionAttr attribute. For each field it calls GetProcAddress and stores the result in the delegate. I wish I could declare the delegate signature and delegate variable in one line. :(

NativePluginLoader.OnDestory calls FreeLibrary for all loaded plugins. The DLLs can then be updated. Next time you run the new DLL will be loaded and the new proc addresses will be found.

The syntax for calling the delegates is identical to using PInvoke. If performance is a concern you can provide a dynamic version inside #if UNITY_EDITOR and rely on PInvoke for standalone builds.

Platforms

This currently only supports Windows. Supporting other platforms should be trivial. Pull requests welcome.

License

The entire repo is dual-licensed under both MIT License and Unlicense.

About

Single-file helper to allow Unity NativePlugins to be updated without restarting the editor.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published