Skip to content

Commit

Permalink
Remove unused code from UnmanagedLibrary (#3799)
Browse files Browse the repository at this point in the history
Co-authored-by: Tig <[email protected]>
  • Loading branch information
kasperk81 and tig authored Oct 28, 2024
1 parent 8f1954f commit 7baede5
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 256 deletions.
268 changes: 15 additions & 253 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#define GUICS
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;

Expand All @@ -27,81 +26,6 @@ namespace Unix.Terminal;
/// </summary>
internal class UnmanagedLibrary
{
private const string UnityEngineApplicationClassName = "UnityEngine.Application, UnityEngine";
private const string XamarinAndroidObjectClassName = "Java.Lang.Object, Mono.Android";
private const string XamarinIOSObjectClassName = "Foundation.NSObject, Xamarin.iOS";
private static readonly bool IsWindows;
private static readonly bool IsLinux;
private static readonly bool Is64Bit;
#if GUICS
private static readonly bool IsMono;
#else
static bool IsMono, IsUnity, IsXamarinIOS, IsXamarinAndroid, IsXamarin;
#endif
private static bool IsNetCore;
public static bool IsMacOSPlatform { get; }

[DllImport ("libc")]
private static extern int uname (nint buf);

private static string GetUname ()
{
nint buffer = Marshal.AllocHGlobal (8192);

try
{
if (uname (buffer) == 0)
{
return Marshal.PtrToStringAnsi (buffer);
}

return string.Empty;
}
catch
{
return string.Empty;
}
finally
{
if (buffer != nint.Zero)
{
Marshal.FreeHGlobal (buffer);
}
}
}

[UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
static UnmanagedLibrary ()
{
PlatformID platform = Environment.OSVersion.Platform;

IsMacOSPlatform = platform == PlatformID.Unix && GetUname () == "Darwin";
IsLinux = platform == PlatformID.Unix && !IsMacOSPlatform;

IsWindows = platform == PlatformID.Win32NT
|| platform == PlatformID.Win32S
|| platform == PlatformID.Win32Windows;
Is64Bit = Marshal.SizeOf (typeof (nint)) == 8;
IsMono = Type.GetType ("Mono.Runtime") != null;

if (!IsMono)
{
IsNetCore = Type.GetType ("System.MathF") != null;
}
#if GUICS

//IsUnity = IsXamarinIOS = IsXamarinAndroid = IsXamarin = false;
#else
IsUnity = Type.GetType (UnityEngineApplicationClassName) != null;
IsXamarinIOS = Type.GetType (XamarinIOSObjectClassName) != null;
IsXamarinAndroid = Type.GetType (XamarinAndroidObjectClassName) != null;
IsXamarin = IsXamarinIOS || IsXamarinAndroid;
#endif
}

// flags for dlopen
private const int RTLD_LAZY = 1;
private const int RTLD_GLOBAL = 8;
public readonly string LibraryPath;
public nint NativeLibraryHandle { get; }

Expand All @@ -114,15 +38,25 @@ public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath)
{
if (isFullPath)
{
LibraryPath = FirstValidLibraryPath (libraryPathAlternatives);
NativeLibraryHandle = PlatformSpecificLoadLibrary (LibraryPath);
foreach (string path in libraryPathAlternatives)
{
if (File.Exists (path))
{
LibraryPath = path;
break;
}
}

if (LibraryPath is null)
throw new FileNotFoundException ($"Error loading native library. Not found in any of the possible locations: {string.Join (",", libraryPathAlternatives)}");

NativeLibraryHandle = NativeLibrary.Load (LibraryPath);
}
else
{
foreach (string lib in libraryPathAlternatives)
{
NativeLibraryHandle = PlatformSpecificLoadLibrary (lib);

NativeLibraryHandle = NativeLibrary.Load (lib);
if (NativeLibraryHandle != nint.Zero)
{
LibraryPath = lib;
Expand All @@ -143,55 +77,7 @@ public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath)
/// <returns></returns>
public nint LoadSymbol (string symbolName)
{
if (IsWindows)
{
// See http://stackoverflow.com/questions/10473310 for background on this.
if (Is64Bit)
{
return Windows.GetProcAddress (NativeLibraryHandle, symbolName);
}

// Yes, we could potentially predict the size... but it's a lot simpler to just try
// all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying
// many options - and if it takes a little bit longer to fail if we've really got the wrong
// library, that's not a big problem. This is only called once per function in the native library.
symbolName = "_" + symbolName + "@";

for (var stackSize = 0; stackSize < 128; stackSize += 4)
{
nint candidate = Windows.GetProcAddress (NativeLibraryHandle, symbolName + stackSize);

if (candidate != nint.Zero)
{
return candidate;
}
}

// Fail.
return nint.Zero;
}

if (IsLinux)
{
if (IsMono)
{
return Mono.dlsym (NativeLibraryHandle, symbolName);
}

if (IsNetCore)
{
return CoreCLR.dlsym (NativeLibraryHandle, symbolName);
}

return Linux.dlsym (NativeLibraryHandle, symbolName);
}

if (IsMacOSPlatform)
{
return MacOSX.dlsym (NativeLibraryHandle, symbolName);
}

throw new InvalidOperationException ("Unsupported platform.");
return NativeLibrary.GetExport(NativeLibraryHandle, symbolName);
}

public T GetNativeMethodDelegate<T> (string methodName)
Expand All @@ -206,128 +92,4 @@ public T GetNativeMethodDelegate<T> (string methodName)

return Marshal.GetDelegateForFunctionPointer<T> (ptr); // non-generic version is obsolete
}

/// <summary>Loads library in a platform specific way.</summary>
private static nint PlatformSpecificLoadLibrary (string libraryPath)
{
if (IsWindows)
{
return Windows.LoadLibrary (libraryPath);
}

if (IsLinux)
{
if (IsMono)
{
return Mono.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}

if (IsNetCore)
{
try
{
return CoreCLR.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}
catch (Exception)
{
IsNetCore = false;
}
}

return Linux.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}

if (IsMacOSPlatform)
{
return MacOSX.dlopen (libraryPath, RTLD_GLOBAL + RTLD_LAZY);
}

throw new InvalidOperationException ("Unsupported platform.");
}

private static string FirstValidLibraryPath (string [] libraryPathAlternatives)
{
foreach (string path in libraryPathAlternatives)
{
if (File.Exists (path))
{
return path;
}
}

throw new FileNotFoundException (
string.Format (
"Error loading native library. Not found in any of the possible locations: {0}",
string.Join (",", libraryPathAlternatives)
)
);
}

private static class Windows
{
[DllImport ("kernel32.dll")]
internal static extern nint GetProcAddress (nint hModule, string procName);

[DllImport ("kernel32.dll")]
internal static extern nint LoadLibrary (string filename);
}

private static class Linux
{
[DllImport ("libdl.so")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("libdl.so")]
internal static extern nint dlsym (nint handle, string symbol);
}

private static class MacOSX
{
[DllImport ("libSystem.dylib")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("libSystem.dylib")]
internal static extern nint dlsym (nint handle, string symbol);
}

/// <summary>
/// On Linux systems, using dlopen and dlsym results in DllNotFoundException("libdl.so not found") if
/// libc6-dev is not installed. As a workaround, we load symbols for dlopen and dlsym from the current process as on
/// Linux Mono sure is linked against these symbols.
/// </summary>
private static class Mono
{
[DllImport ("__Internal")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("__Internal")]
internal static extern nint dlsym (nint handle, string symbol);
}

/// <summary>
/// Similarly as for Mono on Linux, we load symbols for dlopen and dlsym from the "libcoreclr.so", to avoid the
/// dependency on libc-dev Linux.
/// </summary>
private static class CoreCLR
{
// Custom resolver to support true single-file apps
// (those which run directly from bundle; in-memory).
// -1 on Unix means self-referencing binary (libcoreclr.so)
// 0 means fallback to CoreCLR's internal resolution
// Note: meaning of -1 stay the same even for non-single-file form factors.
static CoreCLR ()
{
NativeLibrary.SetDllImportResolver (
typeof (CoreCLR).Assembly,
(libraryName, assembly, searchPath) =>
libraryName == "libcoreclr.so" ? -1 : nint.Zero
);
}

[DllImport ("libcoreclr.so")]
internal static extern nint dlopen (string filename, int flags);

[DllImport ("libcoreclr.so")]
internal static extern nint dlsym (nint handle, string symbol);
}
}
6 changes: 3 additions & 3 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@ private static nint get_ptr (string key)

private static void LoadMethods ()
{
string [] libs = UnmanagedLibrary.IsMacOSPlatform
? new [] { "libncurses.dylib" }
: new [] { "libncursesw.so.6", "libncursesw.so.5" };
string [] libs = OperatingSystem.IsMacOS()
? ["libncurses.dylib"]
: ["libncursesw.so.6", "libncursesw.so.5"];
var attempts = 1;

while (true)
Expand Down

0 comments on commit 7baede5

Please sign in to comment.