diff --git a/DynamicInterop/UnixLibraryLoader.cs b/DynamicInterop/UnixLibraryLoader.cs index d137292..07b71da 100644 --- a/DynamicInterop/UnixLibraryLoader.cs +++ b/DynamicInterop/UnixLibraryLoader.cs @@ -14,7 +14,15 @@ internal class UnixLibraryLoader : IDynamicLibraryLoader { public IntPtr LoadLibrary(string filename) { - return InternalLoadLibrary(filename); + const int RTLD_LAZY = 0x1; + + if (_so == 0) + return InternalLoadLibrary(filename, RTLD_LAZY); + + if (_so == 1) + return dlopen1(filename, RTLD_LAZY); + else + return dlopen2(filename, RTLD_LAZY); } /// @@ -23,7 +31,13 @@ public IntPtr LoadLibrary(string filename) /// The last error. public string GetLastError() { - return dlerror(); + if (_so == 0) + throw new Exception("Called GetLastError before LoadLibrary"); + + if (_so == 1) + return dlerror1(); + else + return dlerror2(); } /// @@ -33,34 +47,48 @@ public string GetLastError() /// True if the function dlclose returned 0 public bool FreeLibrary(IntPtr handle) { + if (_so == 0) + throw new Exception("Called GetLastError before LoadLibrary"); + // according to the manual page on a Debian box // The function dlclose() returns 0 on success, and nonzero on error. - var status = dlclose(handle); - return status == 0; + if (_so == 1) + { + var status = dlclose1(handle); + return status == 0; + } + else + { + var status = dlclose2(handle); + return status == 0; + } } public IntPtr GetFunctionAddress(IntPtr hModule, string lpProcName) { - return dlsym(hModule, lpProcName); + if (_so == 0) + throw new Exception("Called GetLastError before LoadLibrary"); + + if (_so == 1) + return dlsym1(hModule, lpProcName); + else + return dlsym2(hModule, lpProcName); } - internal static IntPtr InternalLoadLibrary(string filename) + internal static IntPtr InternalLoadLibrary(string filename, int lazy) { - const int RTLD_LAZY = 0x1; -// if (filename.StartsWith ("/")) { -// return dlopen (filename, RTLD_LAZY); -// } -// var searchPaths = getSearchPaths ("LD_LIBRARY_PATH"); -// searchPaths.AddRange (getSearchPaths ("PATH")); -// var dll = searchPaths.Select (directory => Path.Combine (directory, filename)).FirstOrDefault (File.Exists); -// if (dll == null) { -// throw new DllNotFoundException ("Could not find the file: " + filename + " on the search path. Checked these directories:\n " -// + String.Join ("\n", searchPaths)); -// } - - var result = dlopen (filename, RTLD_LAZY); - return result; + try + { + var result = dlopen1(filename, lazy); + _so = 1; + return result; + } + catch (DllNotFoundException) + { + _so = 2; + } + return dlopen2(filename, lazy); } static List getSearchPaths(string pathsEnvVar) @@ -69,18 +97,36 @@ static List getSearchPaths(string pathsEnvVar) return searchPaths; } - [DllImport("libdl")] - private static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPStr)] string filename, int flag); + private static int _so = 0; + + [DllImport("libdl.so", EntryPoint = "dlopen")] + private static extern IntPtr dlopen1([MarshalAs(UnmanagedType.LPStr)] string filename, int flag); - [DllImport("libdl")] + [DllImport("libdl.so.2", EntryPoint = "dlopen")] + private static extern IntPtr dlopen2([MarshalAs(UnmanagedType.LPStr)] string filename, int flag); + + + [DllImport("libdl.so", EntryPoint = "dlerror")] + [return: MarshalAs(UnmanagedType.LPStr)] + private static extern string dlerror1(); + + [DllImport("libdl.so.2", EntryPoint = "dlerror")] [return: MarshalAs(UnmanagedType.LPStr)] - private static extern string dlerror(); + private static extern string dlerror2(); - [DllImport("libdl", EntryPoint = "dlclose")] + + [DllImport("libdl.so", EntryPoint = "dlclose")] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + private static extern int dlclose1(IntPtr hModule); + + [DllImport("libdl.so.2", EntryPoint = "dlclose")] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - private static extern int dlclose(IntPtr hModule); + private static extern int dlclose2(IntPtr hModule); + - [DllImport("libdl", EntryPoint = "dlsym")] - private static extern IntPtr dlsym(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); + [DllImport("libdl.so", EntryPoint = "dlsym")] + private static extern IntPtr dlsym1(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); + [DllImport("libdl.so.2", EntryPoint = "dlsym")] + private static extern IntPtr dlsym2(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); } }