using System; using System.Runtime.InteropServices; namespace MonoGame.Utilities { internal class FuncLoader { private class Windows { [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] public static extern IntPtr LoadLibraryW(string lpszLib); } private class Linux { [DllImport("libdl.so.2")] public static extern IntPtr dlopen(string path, int flags); [DllImport("libdl.so.2")] public static extern IntPtr dlsym(IntPtr handle, string symbol); } private class OSX { [DllImport("/usr/lib/libSystem.dylib")] public static extern IntPtr dlopen(string path, int flags); [DllImport("/usr/lib/libSystem.dylib")] public static extern IntPtr dlsym(IntPtr handle, string symbol); } private const int RTLD_LAZY = 0x0001; public static IntPtr LoadLibrary(string libname) { if (CurrentPlatform.OS == OS.Windows) return Windows.LoadLibraryW(libname); if (CurrentPlatform.OS == OS.MacOSX) return OSX.dlopen(libname, RTLD_LAZY); return Linux.dlopen(libname, RTLD_LAZY); } public static T LoadFunction(IntPtr library, string function, bool throwIfNotFound = false) { var ret = IntPtr.Zero; if (CurrentPlatform.OS == OS.Windows) ret = Windows.GetProcAddress(library, function); else if (CurrentPlatform.OS == OS.MacOSX) ret = OSX.dlsym(library, function); else ret = Linux.dlsym(library, function); if (ret == IntPtr.Zero) { if (throwIfNotFound) throw new EntryPointNotFoundException(function); return default(T); } #if NETSTANDARD return Marshal.GetDelegateForFunctionPointer(ret); #else return (T)(object)Marshal.GetDelegateForFunctionPointer(ret, typeof(T)); #endif } } }