-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
45d7805
commit 0cb8c36
Showing
17 changed files
with
623 additions
and
837 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace PdfiumPrinter.LibraryLoader; | ||
|
||
public interface ILibraryLoader | ||
{ | ||
LoadResult OpenLibrary(string fileName); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace PdfiumPrinter.LibraryLoader; | ||
|
||
internal class LinuxLibraryLoader : ILibraryLoader | ||
{ | ||
[DllImport("libdl.so", ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "dlopen")] | ||
public static extern IntPtr NativeOpenLibraryLibdl(string filename, int flags); | ||
|
||
[DllImport("libdl.so.2", ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "dlopen")] | ||
public static extern IntPtr NativeOpenLibraryLibdl2(string filename, int flags); | ||
|
||
[DllImport("libdl.so", ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "dlerror")] | ||
public static extern IntPtr GetLoadError(); | ||
|
||
[DllImport("libdl.so.2", ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "dlerror")] | ||
public static extern IntPtr GetLoadError2(); | ||
|
||
public LoadResult OpenLibrary(string fileName) | ||
{ | ||
IntPtr loadedLib; | ||
try | ||
{ | ||
// open with rtls lazy flag | ||
loadedLib = NativeOpenLibraryLibdl2(fileName, 0x00001); | ||
} | ||
catch (DllNotFoundException) | ||
{ | ||
loadedLib = NativeOpenLibraryLibdl(fileName, 0x00001); | ||
} | ||
|
||
if (loadedLib == IntPtr.Zero) | ||
{ | ||
string errorMessage; | ||
try | ||
{ | ||
errorMessage = Marshal.PtrToStringAnsi(GetLoadError2()) ?? "Unknown error"; | ||
} | ||
catch (DllNotFoundException) | ||
{ | ||
errorMessage = Marshal.PtrToStringAnsi(GetLoadError()) ?? "Unknown error"; | ||
} | ||
|
||
return LoadResult.Failure(errorMessage); | ||
} | ||
|
||
return LoadResult.Success; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
namespace PdfiumPrinter.LibraryLoader; | ||
|
||
public class LoadResult | ||
{ | ||
private LoadResult(bool isSuccess, string errorMessage) | ||
{ | ||
IsSuccess = isSuccess; | ||
ErrorMessage = errorMessage; | ||
} | ||
|
||
public static LoadResult Success { get; } = new(true, null); | ||
|
||
public static LoadResult Failure(string errorMessage) | ||
{ | ||
return new(false, errorMessage); | ||
} | ||
|
||
public bool IsSuccess { get; } | ||
public string ErrorMessage { get; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace PdfiumPrinter.LibraryLoader; | ||
|
||
internal class MacOsLibraryLoader : ILibraryLoader | ||
{ | ||
[DllImport("libdl.dylib", ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "dlopen")] | ||
public static extern IntPtr NativeOpenLibraryLibdl(string filename, int flags); | ||
|
||
[DllImport("libdl.dylib", ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "dlerror")] | ||
public static extern IntPtr GetLoadError(); | ||
|
||
public LoadResult OpenLibrary(string fileName) | ||
{ | ||
var loadedLib = NativeOpenLibraryLibdl(fileName, 0x00001); | ||
|
||
if (loadedLib == IntPtr.Zero) | ||
{ | ||
var errorMessage = Marshal.PtrToStringAnsi(GetLoadError()) ?? "Unknown error"; | ||
|
||
return LoadResult.Failure(errorMessage); | ||
} | ||
|
||
return LoadResult.Success; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#if !IOS && !MACCATALYST && !TVOS && !ANDROID | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.InteropServices; | ||
#endif | ||
|
||
namespace PdfiumPrinter.LibraryLoader; | ||
|
||
public static class NativeLibraryLoader | ||
{ | ||
private static ILibraryLoader defaultLibraryLoader; | ||
|
||
/// <summary> | ||
/// Sets the library loader used to load the native libraries. Overwrite this only if you want some custom loading. | ||
/// </summary> | ||
/// <param name="libraryLoader">The library loader to be used.</param> | ||
/// <remarks> | ||
/// It needs to be set before the first <seealso cref="PdfDocument"/> is created, otherwise it won't have any effect. | ||
/// </remarks> | ||
public static void SetLibraryLoader(ILibraryLoader libraryLoader) | ||
{ | ||
defaultLibraryLoader = libraryLoader; | ||
} | ||
|
||
public static LoadResult LoadNativeLibrary(string path = default, bool bypassLoading = false) | ||
{ | ||
|
||
#if IOS || MACCATALYST || TVOS || ANDROID | ||
// If we're not bypass loading, and the path was set, and loader was set, allow it to go through. | ||
if (!bypassLoading && defaultLibraryLoader != null) | ||
{ | ||
return defaultLibraryLoader.OpenLibrary(path); | ||
} | ||
|
||
return LoadResult.Success; | ||
#else | ||
// If the user has handled loading the library themselves, we don't need to do anything. | ||
if (bypassLoading || RuntimeInformation.OSArchitecture.ToString() == "Wasm") | ||
{ | ||
return LoadResult.Success; | ||
} | ||
|
||
var architecture = RuntimeInformation.OSArchitecture switch | ||
{ | ||
Architecture.X64 => "x64", | ||
Architecture.X86 => "x86", | ||
Architecture.Arm => "arm", | ||
Architecture.Arm64 => "arm64", | ||
_ => throw new PlatformNotSupportedException($"Unsupported OS platform, architecture: {RuntimeInformation.OSArchitecture}") | ||
}; | ||
|
||
var (platform, fileName) = Environment.OSVersion.Platform switch | ||
{ | ||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.Windows) => ("win", "pdfium.dll"), | ||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.Linux) => ("linux", "libpdfium.so"), | ||
_ when RuntimeInformation.IsOSPlatform(OSPlatform.OSX) => ("osx", "libpdfium.dylib"), | ||
_ => throw new PlatformNotSupportedException($"Unsupported OS platform, architecture: {RuntimeInformation.OSArchitecture}") | ||
}; | ||
|
||
if (string.IsNullOrEmpty(path)) | ||
{ | ||
var assemblySearchPath = new[] | ||
{ | ||
AppDomain.CurrentDomain.RelativeSearchPath, | ||
Path.GetDirectoryName(typeof(NativeMethods).Assembly.Location), | ||
Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) | ||
}.Where(it => !string.IsNullOrEmpty(it)).FirstOrDefault(); | ||
|
||
path = string.IsNullOrEmpty(assemblySearchPath) | ||
? Path.Combine("runtimes", $"{platform}-{architecture}", fileName) | ||
: Path.Combine(assemblySearchPath, "runtimes", $"{platform}-{architecture}", "native", fileName); | ||
|
||
} | ||
|
||
if (defaultLibraryLoader != null) | ||
{ | ||
return defaultLibraryLoader.OpenLibrary(path); | ||
} | ||
|
||
if (!File.Exists(path)) | ||
{ | ||
throw new FileNotFoundException($"Native Library not found in path {path}. " + | ||
$"Verify you have have included the native Pdfium library in your application, " + | ||
$"or install the default libraries with the bblanchon.PDFium NuGet."); | ||
} | ||
|
||
ILibraryLoader libraryLoader = platform switch | ||
{ | ||
"win" => new WindowsLibraryLoader(), | ||
"osx" => new MacOsLibraryLoader(), | ||
"linux" => new LinuxLibraryLoader(), | ||
_ => throw new PlatformNotSupportedException($"Currently {platform} platform is not supported") | ||
}; | ||
|
||
var result = libraryLoader.OpenLibrary(path); | ||
return result; | ||
#endif | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace PdfiumPrinter.LibraryLoader; | ||
internal class WindowsLibraryLoader : ILibraryLoader | ||
{ | ||
public LoadResult OpenLibrary(string fileName) | ||
{ | ||
var loadedLib = LoadLibrary(fileName); | ||
|
||
if (loadedLib == IntPtr.Zero) | ||
{ | ||
var errorCode = Marshal.GetLastWin32Error(); | ||
var errorMessage = new Win32Exception(errorCode).Message; | ||
return LoadResult.Failure(errorMessage); | ||
} | ||
|
||
return LoadResult.Success; | ||
} | ||
|
||
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)] | ||
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPTStr)] string lpFileName); | ||
} |
Oops, something went wrong.