forrestthewoods / fts_unity_native_plugin_reloader

Single-file helper to allow Unity NativePlugins to be updated without restarting the editor.
Other
106 stars 16 forks source link

Support non-windows platforms #1

Open forrestthewoods opened 5 years ago

forrestthewoods commented 5 years ago

Would like to support platforms other than Windows. Requires at least two things.

  1. Wrap SystemLibrary methods with platform specific calls.
  2. Provide platform specific library extensions.

Platform system calls may take different parameters. Which may require updated LoadAll as well.

futscdav commented 4 years ago

I adapted this to my needs on Linux, which was fairly simple to do. I might change the Attributes later on, but this has been an excellent starting point. If you are interested, these changes should be sufficient to make it work under Linux (and possibly MacOS and Android too, but I have no way to test that, so I only ifdef LINUX).

Define SystemLibrary based on current OS:

    #if UNITY_STANDALONE_WIN
    static class SystemLibrary
    {
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        static public extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static public extern bool FreeLibrary(IntPtr hModule);

        [DllImport("kernel32")]
        static public extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32.dll")]
        static public extern uint GetLastError();
    }
    #elif UNITY_STANDALONE_LINUX
    static class SystemLibraryLinux
    {
        [DllImport("dl")]
        static public extern IntPtr dlopen(string filename, int flags);

        [DllImport("dl")]
        static public extern int dlclose(IntPtr handle);

        [DllImport("dl")]
        static public extern IntPtr dlsym(IntPtr handle, string symbol);

        [DllImport("dl")]
        static public extern string dlerror();
    }
    static class SystemLibrary
    {
        static public IntPtr LoadLibrary(string lpFileName) {
            var _ = SystemLibraryLinux.dlerror();
            var handle = SystemLibraryLinux.dlopen(lpFileName, 0x00002 | 0x00100); // RTLD_NOW | RTLD_GLOBAL
            return handle;
        }

        static public bool FreeLibrary(IntPtr hModule) {
            var success = SystemLibraryLinux.dlclose(hModule);
            return success == 0;
        }

        static public IntPtr GetProcAddress(IntPtr hModule, string procedureName) {
            var _ = SystemLibraryLinux.dlerror();
            var address = SystemLibraryLinux.dlsym(hModule, procedureName);
            return address;
        }

        static public string GetLastError() {
            var error = SystemLibraryLinux.dlerror();
            return error;
        }
    }
    #endif

Change EXT to platform based

    // Constants
    #if UNITY_STANDALONE_WIN
    const string EXT = ".dll"; // TODO: Handle different platforms
    #elif UNITY_STANDALONE_LINUX
    const string EXT = ".so";
    #endif

The only difference this way is that GetLastError() returns a string but since the LoadAll is using string.Format, it will work.