Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup runtime platform classes #2 #11930

Merged
merged 12 commits into from
Jun 30, 2023
1 change: 1 addition & 0 deletions src/Android/Avalonia.Android/AndroidPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static class AndroidApplicationExtensions
public static AppBuilder UseAndroid(this AppBuilder builder)
{
return builder
.UseStandardRuntimePlatformSubsystem()
.UseWindowingSubsystem(() => AndroidPlatform.Initialize(), "Android")
.UseSkia();
}
Expand Down
122 changes: 122 additions & 0 deletions src/Avalonia.Base/Compatibility/NativeLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using System;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
using Avalonia.Compatibility;
using Avalonia.Platform.Interop;

namespace Avalonia.Compatibility
{
internal class NativeLibraryEx
{
#if NET6_0_OR_GREATER
public static IntPtr Load(string dll, Assembly assembly) => NativeLibrary.Load(dll, assembly, null);
public static IntPtr Load(string dll) => NativeLibrary.Load(dll);
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) =>
NativeLibrary.TryGetExport(handle, name, out address);
#else
public static IntPtr Load(string dll, Assembly assembly) => Load(dll);
public static IntPtr Load(string dll)
{
var handle = DlOpen!(dll);
if (handle != IntPtr.Zero)
return handle;
throw new InvalidOperationException("Unable to load " + dll, DlError!());
}

public static bool TryGetExport(IntPtr handle, string name, out IntPtr address)
{
try
{
address = DlSym!(handle, name);
return address != default;
}
catch (Exception)
{
address = default;
return false;
}
}

static NativeLibraryEx()
{
if (OperatingSystemEx.IsWindows())
{
Win32Imports.Init();
}
else if (OperatingSystemEx.IsLinux() || OperatingSystemEx.IsMacOS())
{
var buffer = Marshal.AllocHGlobal(0x1000);
uname(buffer);
var unixName = Marshal.PtrToStringAnsi(buffer);
Marshal.FreeHGlobal(buffer);
if (unixName == "Darwin")
OsXImports.Init();
else
LinuxImports.Init();
}
}

private static Func<string, IntPtr>? DlOpen;
private static Func<IntPtr, string, IntPtr>? DlSym;
private static Func<Exception?>? DlError;

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

static class Win32Imports
{
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

[DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string lpszLib);

public static void Init()
{
DlOpen = LoadLibrary;
DlSym = GetProcAddress;
DlError = () => new Win32Exception(Marshal.GetLastWin32Error());
}
}

static class LinuxImports
{
[DllImport("libdl.so.2")]
private static extern IntPtr dlopen(string path, int flags);

[DllImport("libdl.so.2")]
private static extern IntPtr dlsym(IntPtr handle, string symbol);

[DllImport("libdl.so.2")]
private static extern IntPtr dlerror();

public static void Init()
{
DlOpen = s => dlopen(s, 1);
DlSym = dlsym;
DlError = () => new InvalidOperationException(Marshal.PtrToStringAnsi(dlerror()));
}
}

static class OsXImports
{
[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlopen(string path, int flags);

[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlsym(IntPtr handle, string symbol);

[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlerror();

public static void Init()
{
DlOpen = s => dlopen(s, 1);
DlSym = dlsym;
DlError = () => new InvalidOperationException(Marshal.PtrToStringAnsi(dlerror()));
}
}
#endif
}
}
16 changes: 2 additions & 14 deletions src/Avalonia.Base/Platform/IRuntimePlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,13 @@

namespace Avalonia.Platform
{
[Unstable]
[PrivateApi]
public interface IRuntimePlatform
{
IDisposable StartSystemTimer(TimeSpan interval, Action tick);
RuntimePlatformInfo GetRuntimeInfo();
IUnmanagedBlob AllocBlob(int size);
}

[Unstable]
public interface IUnmanagedBlob : IDisposable
{
IntPtr Address { get; }
int Size { get; }
bool IsDisposed { get; }

}

[Unstable]
[PrivateApi]
public record struct RuntimePlatformInfo
{
public FormFactorType FormFactor => IsDesktop ? FormFactorType.Desktop :
Expand All @@ -29,7 +18,6 @@ public record struct RuntimePlatformInfo
public bool IsMobile { get; set; }
}

[Unstable]
public enum FormFactorType
{
Unknown,
Expand Down
161 changes: 0 additions & 161 deletions src/Avalonia.Base/Platform/Internal/DynLoader.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Avalonia.Base/Platform/Internal/UnmanagedBlob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Avalonia.Platform.Internal;

internal class UnmanagedBlob : IUnmanagedBlob
internal class UnmanagedBlob
{
private IntPtr _address;
private readonly object _lock = new object();
Expand Down
24 changes: 0 additions & 24 deletions src/Avalonia.Base/Platform/Interop/IDynamicLibraryLoader.cs

This file was deleted.

12 changes: 3 additions & 9 deletions src/Avalonia.Base/Platform/StandardRuntimePlatform.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
using System;
using System.Threading;
using Avalonia.Compatibility;
using Avalonia.Metadata;
using Avalonia.Platform.Internal;

namespace Avalonia.Platform
{
[PrivateApi]
public class StandardRuntimePlatform : IRuntimePlatform
{
public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
{
return new Timer(_ => tick(), null, interval, interval);
}

public IUnmanagedBlob AllocBlob(int size) => new UnmanagedBlob(size);

private static readonly RuntimePlatformInfo s_info = new()
{
IsDesktop = OperatingSystemEx.IsWindows() || OperatingSystemEx.IsMacOS() || OperatingSystemEx.IsLinux(),
IsMobile = OperatingSystemEx.IsAndroid() || OperatingSystemEx.IsIOS()
};



public virtual RuntimePlatformInfo GetRuntimeInfo() => s_info;
}
}
Loading