Load specific native libraries on desktop/netfx
This fixes 2 issues: - loading multiple versions of libSkiaSharp (#1252) - resolving the issue with 32/64 bit dll (#713)
This commit is contained in:
Родитель
c23eab0bf9
Коммит
7cda786b8a
|
@ -0,0 +1,198 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#if HARFBUZZ
|
||||
namespace HarfBuzzSharp
|
||||
#else
|
||||
namespace SkiaSharp
|
||||
#endif
|
||||
{
|
||||
#if USE_DELEGATES || USE_LIBRARY_LOADER
|
||||
internal static class LibraryLoader
|
||||
{
|
||||
static LibraryLoader ()
|
||||
{
|
||||
if (PlatformConfiguration.IsWindows)
|
||||
Extension = ".dll";
|
||||
else if (PlatformConfiguration.IsMac)
|
||||
Extension = ".dylib";
|
||||
else
|
||||
Extension = ".so";
|
||||
}
|
||||
|
||||
public static string Extension { get; }
|
||||
|
||||
public static IntPtr LoadLocalLibrary<T> (string libraryName)
|
||||
{
|
||||
var libraryPath = GetLibraryPath (libraryName);
|
||||
|
||||
var handle = LoadLibrary (libraryPath);
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new DllNotFoundException ($"Unable to load library '{libraryName}'.");
|
||||
|
||||
return handle;
|
||||
|
||||
static string GetLibraryPath (string libraryName)
|
||||
{
|
||||
var arch = IntPtr.Size == 8 ? "x64" : "x86";
|
||||
|
||||
var libWithExt = libraryName;
|
||||
if (!libraryName.EndsWith (Extension, StringComparison.OrdinalIgnoreCase))
|
||||
libWithExt += Extension;
|
||||
|
||||
// 1. try alongside managed assembly
|
||||
var path = typeof (T).Assembly.Location;
|
||||
if (!string.IsNullOrEmpty (path)) {
|
||||
path = Path.GetDirectoryName (path);
|
||||
// 1.1 in platform sub dir
|
||||
path = Path.Combine (path, arch, libWithExt);
|
||||
if (File.Exists (path))
|
||||
return path;
|
||||
// 1.2 in root
|
||||
path = Path.Combine (path, libWithExt);
|
||||
if (File.Exists (path))
|
||||
return path;
|
||||
}
|
||||
|
||||
// 2. try current directory
|
||||
path = Directory.GetCurrentDirectory ();
|
||||
if (!string.IsNullOrEmpty (path)) {
|
||||
// 2.1 in platform sub dir
|
||||
path = Path.Combine (path, arch, libWithExt);
|
||||
if (File.Exists (path))
|
||||
return path;
|
||||
// 2.2 in root
|
||||
path = Path.Combine (path, libWithExt);
|
||||
if (File.Exists (path))
|
||||
return path;
|
||||
}
|
||||
|
||||
// 3. use PATH or default loading mechanism
|
||||
return libraryName;
|
||||
}
|
||||
}
|
||||
|
||||
public static T GetSymbolDelegate<T> (IntPtr library, string name)
|
||||
where T : Delegate
|
||||
{
|
||||
var symbol = GetSymbol (library, name);
|
||||
if (symbol == IntPtr.Zero)
|
||||
throw new EntryPointNotFoundException ($"Unable to load symbol '{name}'.");
|
||||
|
||||
#if __NET_45__
|
||||
return (T)Marshal.GetDelegateForFunctionPointer (symbol, typeof (T));
|
||||
#else
|
||||
return Marshal.GetDelegateForFunctionPointer<T> (symbol);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static IntPtr LoadLibrary (string libraryName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (libraryName))
|
||||
throw new ArgumentNullException (nameof (libraryName));
|
||||
|
||||
IntPtr handle;
|
||||
if (PlatformConfiguration.IsWindows)
|
||||
handle = Win32.LoadLibrary (libraryName);
|
||||
else if (PlatformConfiguration.IsLinux)
|
||||
handle = Linux.dlopen (libraryName);
|
||||
else if (PlatformConfiguration.IsMac)
|
||||
handle = Mac.dlopen (libraryName);
|
||||
else
|
||||
throw new PlatformNotSupportedException ($"Current platform is unknown, unable to load library '{libraryName}'.");
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public static IntPtr GetSymbol (IntPtr library, string symbolName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (symbolName))
|
||||
throw new ArgumentNullException (nameof (symbolName));
|
||||
|
||||
IntPtr handle;
|
||||
if (PlatformConfiguration.IsWindows)
|
||||
handle = Win32.GetProcAddress (library, symbolName);
|
||||
else if (PlatformConfiguration.IsLinux)
|
||||
handle = Linux.dlsym (library, symbolName);
|
||||
else if (PlatformConfiguration.IsMac)
|
||||
handle = Mac.dlsym (library, symbolName);
|
||||
else
|
||||
throw new PlatformNotSupportedException ($"Current platform is unknown, unable to load symbol '{symbolName}' from library {library}.");
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public static void FreeLibrary (IntPtr library)
|
||||
{
|
||||
if (library == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
if (PlatformConfiguration.IsWindows)
|
||||
Win32.FreeLibrary (library);
|
||||
else if (PlatformConfiguration.IsLinux)
|
||||
Linux.dlclose (library);
|
||||
else if (PlatformConfiguration.IsMac)
|
||||
Mac.dlclose (library);
|
||||
else
|
||||
throw new PlatformNotSupportedException ($"Current platform is unknown, unable to close library '{library}'.");
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
private static class Mac
|
||||
{
|
||||
private const string SystemLibrary = "/usr/lib/libSystem.dylib";
|
||||
|
||||
private const int RTLD_LAZY = 1;
|
||||
private const int RTLD_NOW = 2;
|
||||
|
||||
public static IntPtr dlopen (string path, bool lazy = true) =>
|
||||
dlopen (path, lazy ? RTLD_LAZY : RTLD_NOW);
|
||||
|
||||
[DllImport (SystemLibrary)]
|
||||
public static extern IntPtr dlopen (string path, int mode);
|
||||
|
||||
[DllImport (SystemLibrary)]
|
||||
public static extern IntPtr dlsym (IntPtr handle, string symbol);
|
||||
|
||||
[DllImport (SystemLibrary)]
|
||||
public static extern void dlclose (IntPtr handle);
|
||||
}
|
||||
|
||||
private static class Linux
|
||||
{
|
||||
private const string SystemLibrary = "libdl.so";
|
||||
|
||||
private const int RTLD_LAZY = 1;
|
||||
private const int RTLD_NOW = 2;
|
||||
|
||||
public static IntPtr dlopen (string path, bool lazy = true) =>
|
||||
dlopen (path, lazy ? RTLD_LAZY : RTLD_NOW);
|
||||
|
||||
[DllImport (SystemLibrary)]
|
||||
public static extern IntPtr dlopen (string path, int mode);
|
||||
|
||||
[DllImport (SystemLibrary)]
|
||||
public static extern IntPtr dlsym (IntPtr handle, string symbol);
|
||||
|
||||
[DllImport (SystemLibrary)]
|
||||
public static extern void dlclose (IntPtr handle);
|
||||
}
|
||||
|
||||
private static class Win32
|
||||
{
|
||||
private const string SystemLibrary = "Kernel32.dll";
|
||||
|
||||
[DllImport (SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr LoadLibrary (string lpFileName);
|
||||
|
||||
[DllImport (SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr GetProcAddress (IntPtr hModule, string lpProcName);
|
||||
|
||||
[DllImport (SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern void FreeLibrary (IntPtr hModule);
|
||||
}
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#if HARFBUZZ
|
||||
|
@ -11,20 +10,62 @@ namespace SkiaSharp
|
|||
internal static class PlatformConfiguration
|
||||
{
|
||||
public static bool IsUnix { get; }
|
||||
|
||||
public static bool IsWindows { get; }
|
||||
|
||||
public static bool IsMac { get; }
|
||||
|
||||
public static bool IsLinux { get; }
|
||||
|
||||
static PlatformConfiguration ()
|
||||
{
|
||||
#if WINDOWS_UWP
|
||||
IsMac = false;
|
||||
IsLinux = false;
|
||||
IsUnix = false;
|
||||
IsWindows = true;
|
||||
#elif NET_STANDARD
|
||||
IsUnix = RuntimeInformation.IsOSPlatform (OSPlatform.OSX) || RuntimeInformation.IsOSPlatform (OSPlatform.Linux);
|
||||
#elif NET_STANDARD || __NET_46__
|
||||
IsMac = RuntimeInformation.IsOSPlatform (OSPlatform.OSX);
|
||||
IsLinux = RuntimeInformation.IsOSPlatform (OSPlatform.Linux);
|
||||
IsUnix = IsMac || IsLinux;
|
||||
IsWindows = RuntimeInformation.IsOSPlatform (OSPlatform.Windows);
|
||||
#else
|
||||
IsUnix = Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix;
|
||||
IsWindows = !IsUnix;
|
||||
IsMac = IsUnix && MacPlatformDetector.IsMac.Value;
|
||||
IsLinux = IsUnix && !IsMac;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !NET_STANDARD && !__NET_46__
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
private static class MacPlatformDetector
|
||||
{
|
||||
internal static readonly Lazy<bool> IsMac = new Lazy<bool> (IsRunningOnMac);
|
||||
|
||||
[DllImport ("libc")]
|
||||
static extern int uname (IntPtr buf);
|
||||
|
||||
static bool IsRunningOnMac ()
|
||||
{
|
||||
IntPtr buf = IntPtr.Zero;
|
||||
try {
|
||||
buf = Marshal.AllocHGlobal (8192);
|
||||
// This is a hacktastic way of getting sysname from uname ()
|
||||
if (uname (buf) == 0) {
|
||||
string os = Marshal.PtrToStringAnsi (buf);
|
||||
if (os == "Darwin")
|
||||
return true;
|
||||
}
|
||||
} catch {
|
||||
} finally {
|
||||
if (buf != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace SkiaSharp
|
||||
using System;
|
||||
|
||||
namespace SkiaSharp
|
||||
{
|
||||
internal partial class SkiaApi
|
||||
{
|
||||
|
@ -21,5 +23,18 @@
|
|||
#else
|
||||
private const string SKIA = "libSkiaSharp";
|
||||
#endif
|
||||
|
||||
#if USE_DELEGATES
|
||||
private static IntPtr libSkiaSharpHandle;
|
||||
|
||||
private static T Get<T> (string name)
|
||||
where T : Delegate
|
||||
{
|
||||
if (libSkiaSharpHandle == IntPtr.Zero)
|
||||
libSkiaSharpHandle = LibraryLoader.LoadLocalLibrary<SkiaApi> (SKIA);
|
||||
|
||||
return LibraryLoader.GetSymbolDelegate<T> (libSkiaSharpHandle, name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -152,7 +152,7 @@ namespace SkiaSharp
|
|||
if (data.Length == 0)
|
||||
return string.Empty;
|
||||
|
||||
#if __DESKTOP__
|
||||
#if __NET_45__
|
||||
// TODO: improve this copy for old .NET 4.5
|
||||
var array = data.ToArray ();
|
||||
return encoding switch
|
||||
|
|
|
@ -8,8 +8,14 @@
|
|||
<PropertyGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
|
||||
<DefineConstants>$(DefineConstants);NET_STANDARD</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith('net4'))">
|
||||
<DefineConstants>$(DefineConstants);USE_DELEGATES;__DESKTOP__</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith('net45'))">
|
||||
<DefineConstants>$(DefineConstants);__DESKTOP__</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);__NET_45__</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith('net46'))">
|
||||
<DefineConstants>$(DefineConstants);__NET_46__</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
|
||||
<PackageReference Include="System.IO.UnmanagedMemoryStream" Version="4.3.0" />
|
||||
|
|
|
@ -100,10 +100,14 @@
|
|||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\output\native\windows\$(Platform)\libSkiaSharp.dll" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\$(Platform)\libSkiaSharp.dll') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\$(Platform)\libSkiaSharp.pdb" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\$(Platform)\libSkiaSharp.pdb') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\x64\libSkiaSharp.dll" Link="x64\libSkiaSharp.dll" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\x64\libSkiaSharp.dll') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\x64\libSkiaSharp.pdb" Link="x64\libSkiaSharp.pdb" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\x64\libSkiaSharp.pdb') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\x86\libSkiaSharp.dll" Link="x86\libSkiaSharp.dll" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\x86\libSkiaSharp.dll') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\x86\libSkiaSharp.pdb" Link="x86\libSkiaSharp.pdb" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\x64\libSkiaSharp.pdb') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\$(Platform)\libHarfBuzzSharp.dll" CopyToOutputDirectory="Always" Visible="false"
|
||||
Condition=" Exists('..\..\output\native\windows\$(Platform)\libHarfBuzzSharp.dll') or '$(IsWindows)' == 'true' " />
|
||||
<Content Include="..\..\output\native\windows\$(Platform)\libHarfBuzzSharp.pdb" CopyToOutputDirectory="Always" Visible="false"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<DefineConstants>$(DefineConstants);NET_STANDARD</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);NET_STANDARD;USE_LIBRARY_LOADER</DefineConstants>
|
||||
<RootNamespace>SkiaSharp.Tests</RootNamespace>
|
||||
<AssemblyName>SkiaSharp.Tests</AssemblyName>
|
||||
<SkipGenerateAssemblyVersionInfo>true</SkipGenerateAssemblyVersionInfo>
|
||||
|
@ -21,6 +21,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Tests\**\*.cs" Link="%(RecursiveDir)%(FileName)%(Extension)" />
|
||||
<Compile Include="..\..\binding\Binding.Shared\LibraryLoader.cs" Link="PlatformUtils\LibraryLoader.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\Content\**\*" Link="%(RecursiveDir)%(FileName)%(Extension)" CopyToOutputDirectory="Always" />
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SkiaSharp.Tests
|
||||
{
|
||||
|
@ -11,10 +10,10 @@ namespace SkiaSharp.Tests
|
|||
protected const string GpuCategory = "GPU";
|
||||
protected const string MatchCharacterCategory = "MatchCharacter";
|
||||
|
||||
protected static bool IsLinux;
|
||||
protected static bool IsMac;
|
||||
protected static bool IsUnix;
|
||||
protected static bool IsWindows;
|
||||
protected static bool IsLinux = PlatformConfiguration.IsLinux;
|
||||
protected static bool IsMac = PlatformConfiguration.IsMac;
|
||||
protected static bool IsUnix = PlatformConfiguration.IsUnix;
|
||||
protected static bool IsWindows = PlatformConfiguration.IsWindows;
|
||||
|
||||
protected static bool IsRuntimeMono;
|
||||
|
||||
|
@ -54,19 +53,6 @@ namespace SkiaSharp.Tests
|
|||
}
|
||||
#endif
|
||||
|
||||
// set the OS fields
|
||||
#if NET_STANDARD
|
||||
IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
||||
IsMac = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
||||
IsUnix = IsLinux || IsMac;
|
||||
IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
#else
|
||||
IsMac = MacPlatformDetector.IsMac.Value;
|
||||
IsUnix = Environment.OSVersion.Platform == PlatformID.Unix || IsMac;
|
||||
IsLinux = IsUnix && !IsMac;
|
||||
IsWindows = !IsUnix;
|
||||
#endif
|
||||
|
||||
IsRuntimeMono = Type.GetType("Mono.Runtime") != null;
|
||||
|
||||
// set the test fields
|
||||
|
@ -82,71 +68,5 @@ namespace SkiaSharp.Tests
|
|||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
|
||||
private static class MacPlatformDetector
|
||||
{
|
||||
internal static readonly Lazy<bool> IsMac = new Lazy<bool>(IsRunningOnMac);
|
||||
|
||||
[DllImport("libc")]
|
||||
static extern int uname(IntPtr buf);
|
||||
|
||||
static bool IsRunningOnMac()
|
||||
{
|
||||
IntPtr buf = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
buf = Marshal.AllocHGlobal(8192);
|
||||
// This is a hacktastic way of getting sysname from uname ()
|
||||
if (uname(buf) == 0)
|
||||
{
|
||||
string os = Marshal.PtrToStringAnsi(buf);
|
||||
if (os == "Darwin")
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buf != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MacDynamicLibraries
|
||||
{
|
||||
private const string SystemLibrary = "/usr/lib/libSystem.dylib";
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr dlopen(string path, int mode);
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr dlsym(IntPtr handle, string symbol);
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern void dlclose(IntPtr handle);
|
||||
}
|
||||
|
||||
public static class LinuxDynamicLibraries
|
||||
{
|
||||
private const string SystemLibrary = "libdl.so";
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr dlopen(string path, int mode);
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr dlsym(IntPtr handle, string symbol);
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern void dlclose(IntPtr handle);
|
||||
}
|
||||
|
||||
public static class WindowsDynamicLibraries
|
||||
{
|
||||
private const string SystemLibrary = "Kernel32.dll";
|
||||
[DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr LoadLibrary(string lpFileName);
|
||||
[DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
[DllImport(SystemLibrary, SetLastError = true, CharSet = CharSet.Ansi)]
|
||||
public static extern void FreeLibrary(IntPtr hModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,21 +37,21 @@ namespace SkiaSharp.Tests
|
|||
ctx.MakeCurrent();
|
||||
|
||||
if (IsMac) {
|
||||
var lib = MacDynamicLibraries.dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", 1);
|
||||
var lib = LibraryLoader.LoadLibrary("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
|
||||
|
||||
var glInterface = GRGlInterface.Create(name => {
|
||||
return MacDynamicLibraries.dlsym(lib, name);
|
||||
return LibraryLoader.GetSymbol(lib, name);
|
||||
});
|
||||
|
||||
Assert.NotNull(glInterface);
|
||||
Assert.True(glInterface.Validate());
|
||||
|
||||
MacDynamicLibraries.dlclose(lib);
|
||||
LibraryLoader.FreeLibrary(lib);
|
||||
} else if (IsWindows) {
|
||||
var lib = WindowsDynamicLibraries.LoadLibrary("opengl32.dll");
|
||||
var lib = LibraryLoader.LoadLibrary("opengl32.dll");
|
||||
|
||||
var glInterface = GRGlInterface.Create(name => {
|
||||
var ptr = WindowsDynamicLibraries.GetProcAddress(lib, name);
|
||||
var ptr = LibraryLoader.GetSymbol(lib, name);
|
||||
if (ptr == IntPtr.Zero) {
|
||||
ptr = wglGetProcAddress(name);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ namespace SkiaSharp.Tests
|
|||
Assert.NotNull(glInterface);
|
||||
Assert.True(glInterface.Validate());
|
||||
|
||||
WindowsDynamicLibraries.FreeLibrary(lib);
|
||||
LibraryLoader.FreeLibrary(lib);
|
||||
} else if (IsLinux) {
|
||||
var glInterface = GRGlInterface.Create(name => {
|
||||
return glXGetProcAddress(name);
|
||||
|
|
|
@ -333,14 +333,11 @@ namespace SkiaSharpGenerator
|
|||
{
|
||||
Log?.LogVerbose($" {function.Name}");
|
||||
|
||||
writer.WriteLine();
|
||||
writer.WriteLine($"\t\t// {function}");
|
||||
writer.WriteLine($"\t\t[DllImport ({config.DllName}, CallingConvention = CallingConvention.Cdecl)]");
|
||||
|
||||
var name = function.Name;
|
||||
functionMappings.TryGetValue(name, out var funcMap);
|
||||
|
||||
var paramsList = new List<string>();
|
||||
var paramNamesList = new List<string>();
|
||||
for (var i = 0; i < function.Parameters.Count; i++)
|
||||
{
|
||||
var p = function.Parameters[i];
|
||||
|
@ -352,9 +349,11 @@ namespace SkiaSharpGenerator
|
|||
if (funcMap != null && funcMap.Parameters.TryGetValue(i.ToString(), out var newT))
|
||||
t = newT;
|
||||
paramsList.Add($"{t} {n}");
|
||||
paramNamesList.Add(n);
|
||||
}
|
||||
|
||||
var returnType = GetType(function.ReturnType);
|
||||
var retAttr = "";
|
||||
if (funcMap != null && funcMap.Parameters.TryGetValue("-1", out var newR))
|
||||
{
|
||||
returnType = newR;
|
||||
|
@ -362,9 +361,27 @@ namespace SkiaSharpGenerator
|
|||
else if (GetCppType(function.ReturnType) == "bool")
|
||||
{
|
||||
returnType = "bool";
|
||||
writer.WriteLine($"\t\t[return: MarshalAs (UnmanagedType.I1)]");
|
||||
retAttr = $"[return: MarshalAs (UnmanagedType.I1)]";
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
writer.WriteLine($"\t\t// {function}");
|
||||
writer.WriteLine($"\t\t#if !USE_DELEGATES");
|
||||
writer.WriteLine($"\t\t[DllImport ({config.DllName}, CallingConvention = CallingConvention.Cdecl)]");
|
||||
if (!string.IsNullOrEmpty(retAttr))
|
||||
writer.WriteLine($"\t\t{retAttr}");
|
||||
writer.WriteLine($"\t\tinternal static extern {returnType} {name} ({string.Join(", ", paramsList)});");
|
||||
writer.WriteLine($"\t\t#else");
|
||||
writer.WriteLine($"\t\tprivate partial class Delegates {{");
|
||||
writer.WriteLine($"\t\t\t[UnmanagedFunctionPointer(CallingConvention.Cdecl)]");
|
||||
if (!string.IsNullOrEmpty(retAttr))
|
||||
writer.WriteLine($"\t\t\t{retAttr}");
|
||||
writer.WriteLine($"\t\t\tinternal delegate {returnType} {name} ({string.Join(", ", paramsList)});");
|
||||
writer.WriteLine($"\t\t}}");
|
||||
writer.WriteLine($"\t\tprivate static Delegates.{name} {name}_delegate;");
|
||||
writer.WriteLine($"\t\tinternal static {returnType} {name} ({string.Join(", ", paramsList)}) =>");
|
||||
writer.WriteLine($"\t\t\t({name}_delegate ??= Get<Delegates.{name}>(\"{name}\")).Invoke({string.Join(", ", paramNamesList)});");
|
||||
writer.WriteLine($"\t\t#endif");
|
||||
}
|
||||
writer.WriteLine();
|
||||
writer.WriteLine($"\t\t#endregion");
|
||||
|
|
Загрузка…
Ссылка в новой задаче