Skip to content

Commit c7d4b29

Browse files
authored
Merge pull request #140 from ArtifexSoftware/linux-support
added support for linux
2 parents 3f6e508 + 9793aaa commit c7d4b29

File tree

9 files changed

+911
-34
lines changed

9 files changed

+911
-34
lines changed

Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithMustangSample.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void Start()
4949
string outfilename = "my-factur-x-mustang-sample.xml";
5050
File.WriteAllBytes(outfilename, zf2p.getXML());
5151

52-
string gsFilePath = @"C:\Program Files\gs\gs10.05.0\bin\gsdll64.dll";
52+
string gsFilePath = @"C:\Program Files\gs\gs10.06.0\bin\gsdll64.dll";
5353
Console.WriteLine("Using Ghostscript filepath: " + gsFilePath);
5454
Console.WriteLine("Ensure this is the filepath to your installed Ghostscript!");
5555

Ghostscript.NET.PDFA3Converter.Samples/Samples/FacturXWithZUGFeRDcsharpSample.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void Start()
4242
InvoiceDescriptor invoice = CreateInvoice();
4343
invoice.Save(outFilename, ZUGFeRDVersion.Version22, s2industries.ZUGFeRD.Profile.Comfort);
4444

45-
string gsFilePath = @"C:\Program Files\gs\gs10.05.0\bin\gsdll64.dll";
45+
string gsFilePath = @"C:\Program Files\gs\gs10.06.0\bin\gsdll64.dll";
4646
Console.WriteLine("Using Ghostscript filepath: "+ gsFilePath);
4747
Console.WriteLine("Ensure this is the filepath to your installed Ghostscript!");
4848
PDFA3Converter converter = new PDFA3Converter(gsFilePath);

Ghostscript.NET/Ghostscript.NET.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\Ghostscript.NET.xml</DocumentationFile>
77
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
88
<Title>Ghostscript.NET</Title>
9-
<Version>1.3.0</Version>
9+
<Version>1.3.1</Version>
1010
<Authors>Artifex Software Inc.</Authors>
1111
<Company>Artifex</Company>
1212
<Description>A C# binding for Ghostscript library</Description>

Ghostscript.NET/GhostscriptLibrary.cs

Lines changed: 171 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
using System;
2828
using System.IO;
29+
using System.Runtime.InteropServices;
2930
using Microsoft.WinAny.Interop;
3031

3132
namespace Ghostscript.NET
@@ -40,9 +41,11 @@ public class GhostscriptLibrary : IDisposable
4041

4142
private bool _disposed = false;
4243
private DynamicNativeLibrary _library;
44+
private CrossPlatformNativeLibrary _crossPlatformLibrary;
4345
private GhostscriptVersionInfo _version;
4446
private bool _loadedFromMemory = false;
4547
private int _revision;
48+
private bool _isWindows;
4649

4750
#endregion
4851

@@ -60,18 +63,25 @@ public GhostscriptLibrary(byte[] library)
6063
throw new ArgumentNullException("library");
6164
}
6265

63-
// check if library is compatibile with a running process
64-
if (Environment.Is64BitProcess != NativeLibraryHelper.Is64BitLibrary(library))
65-
{
66-
// throw friendly gsdll incompatibility message
67-
this.ThrowIncompatibileNativeGhostscriptLibraryException();
68-
}
66+
_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
67+
_loadedFromMemory = true;
6968

70-
// create DynamicNativeLibrary instance from the memory buffer
71-
_library = new DynamicNativeLibrary(library);
69+
if (_isWindows)
70+
{
71+
// check if library is compatibile with a running process
72+
if (Environment.Is64BitProcess != NativeLibraryHelper.Is64BitLibrary(library))
73+
{
74+
// throw friendly gsdll incompatibility message
75+
this.ThrowIncompatibileNativeGhostscriptLibraryException();
76+
}
7277

73-
// set the flag that the library is loaded from the memory
74-
_loadedFromMemory = true;
78+
// create DynamicNativeLibrary instance from the memory buffer
79+
_library = new DynamicNativeLibrary(library);
80+
}
81+
else
82+
{
83+
throw new NotSupportedException("Loading libraries from memory is only supported on Windows.");
84+
}
7585

7686
// get and map native library symbols
7787
this.Initialize();
@@ -86,7 +96,7 @@ public GhostscriptLibrary(byte[] library)
8696
/// from the GhostscriptVersionInfo object.
8797
/// </summary>
8898
/// <param name="version">GhostscriptVersionInfo instance that tells which Ghostscript library to use.</param>
89-
public GhostscriptLibrary(GhostscriptVersionInfo version) : this(version, false)
99+
public GhostscriptLibrary(GhostscriptVersionInfo version) : this(version, false)
90100
{ }
91101

92102
#endregion
@@ -115,27 +125,41 @@ public GhostscriptLibrary(GhostscriptVersionInfo version, bool fromMemory)
115125

116126
_version = version;
117127
_loadedFromMemory = fromMemory;
128+
_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
118129

119130
// check if library is compatibile with a running process
120-
if (Environment.Is64BitProcess != NativeLibraryHelper.Is64BitLibrary(version.DllPath))
131+
if (!CrossPlatformNativeLibraryHelper.IsLibraryCompatible(version.DllPath))
121132
{
122-
// throw friendly gsdll incompatibility message
133+
// throw friendly library incompatibility message
123134
this.ThrowIncompatibileNativeGhostscriptLibraryException();
124135
}
125136

126137
// check wether we need to load Ghostscript native library from the memory or a disk
127138
if (fromMemory)
128139
{
129-
// load native Ghostscript library into the memory
130-
byte[] buffer = File.ReadAllBytes(version.DllPath);
131-
132-
// create DynamicNativeLibrary instance from the memory buffer
133-
_library = new DynamicNativeLibrary(buffer);
140+
if (_isWindows)
141+
{
142+
// load native Ghostscript library into the memory (Windows only)
143+
byte[] buffer = File.ReadAllBytes(version.DllPath);
144+
_library = new DynamicNativeLibrary(buffer);
145+
}
146+
else
147+
{
148+
throw new NotSupportedException("Loading libraries from memory is only supported on Windows.");
149+
}
134150
}
135151
else
136152
{
137-
// create DynamicNativeLibrary instance from the local disk file
138-
_library = new DynamicNativeLibrary(version.DllPath);
153+
if (_isWindows)
154+
{
155+
// create DynamicNativeLibrary instance from the local disk file (Windows)
156+
_library = new DynamicNativeLibrary(version.DllPath);
157+
}
158+
else
159+
{
160+
// create CrossPlatformNativeLibrary instance for Linux
161+
_crossPlatformLibrary = new CrossPlatformNativeLibrary(version.DllPath);
162+
}
139163
}
140164

141165
// get and map native library symbols
@@ -179,8 +203,17 @@ protected virtual void Dispose(bool disposing)
179203
{
180204
if (disposing)
181205
{
182-
_library.Dispose();
183-
_library = null;
206+
if (_library != null)
207+
{
208+
_library.Dispose();
209+
_library = null;
210+
}
211+
212+
if (_crossPlatformLibrary != null)
213+
{
214+
_crossPlatformLibrary.Dispose();
215+
_crossPlatformLibrary = null;
216+
}
184217
}
185218

186219
_disposed = true;
@@ -218,11 +251,26 @@ protected virtual void Dispose(bool disposing)
218251
/// Get the native library symbols and map them to the appropriate functions/delegates.
219252
/// </summary>
220253
private void Initialize()
254+
{
255+
if (_isWindows)
256+
{
257+
InitializeWindows();
258+
}
259+
else
260+
{
261+
InitializeLinux();
262+
}
263+
}
264+
265+
/// <summary>
266+
/// Initialize Windows-specific library symbols.
267+
/// </summary>
268+
private void InitializeWindows()
221269
{
222270
string symbolMappingError = "Delegate of an exported function couldn't be created for symbol '{0}'";
223271

224272
this.gsapi_revision = _library.GetDelegateForFunction<gsapi_revision>("gsapi_revision");
225-
273+
226274
if (this.gsapi_revision == null)
227275
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_revision"));
228276

@@ -280,7 +328,7 @@ private void Initialize()
280328
if (this.gsapi_run_string_continue == null)
281329
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string_continue"));
282330

283-
this.gsapi_run_string_end = _library.GetDelegateForFunction< gsapi_run_string_end>("gsapi_run_string_end");
331+
this.gsapi_run_string_end = _library.GetDelegateForFunction<gsapi_run_string_end>("gsapi_run_string_end");
284332

285333
if (this.gsapi_run_string_end == null)
286334
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string_end"));
@@ -309,23 +357,116 @@ private void Initialize()
309357

310358
if (this.gsapi_exit == null)
311359
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_exit"));
360+
}
361+
362+
/// <summary>
363+
/// Initialize Linux-specific library symbols.
364+
/// </summary>
365+
private void InitializeLinux()
366+
{
367+
string symbolMappingError = "Delegate of an exported function couldn't be created for symbol '{0}'";
368+
369+
this.gsapi_revision = _crossPlatformLibrary.GetDelegateForFunction<gsapi_revision>("gsapi_revision");
370+
371+
if (this.gsapi_revision == null)
372+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_revision"));
373+
374+
gsapi_revision_s rev = new gsapi_revision_s();
375+
if (this.gsapi_revision(ref rev, System.Runtime.InteropServices.Marshal.SizeOf(rev)) == 0)
376+
{
377+
_revision = rev.revision;
378+
}
379+
380+
this.gsapi_new_instance = _crossPlatformLibrary.GetDelegateForFunction<gsapi_new_instance>("gsapi_new_instance");
381+
382+
if (this.gsapi_new_instance == null)
383+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_new_instance"));
384+
385+
this.gsapi_delete_instance = _crossPlatformLibrary.GetDelegateForFunction<gsapi_delete_instance>("gsapi_delete_instance");
312386

387+
if (this.gsapi_delete_instance == null)
388+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_delete_instance"));
389+
390+
this.gsapi_set_stdio = _crossPlatformLibrary.GetDelegateForFunction<gsapi_set_stdio>("gsapi_set_stdio");
391+
392+
if (this.gsapi_set_stdio == null)
393+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_set_stdio"));
394+
395+
this.gsapi_set_poll = _crossPlatformLibrary.GetDelegateForFunction<gsapi_set_poll>("gsapi_set_poll");
396+
397+
if (this.gsapi_set_poll == null)
398+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_set_poll"));
399+
400+
this.gsapi_set_display_callback = _crossPlatformLibrary.GetDelegateForFunction<gsapi_set_display_callback>("gsapi_set_display_callback");
401+
402+
if (this.gsapi_set_display_callback == null)
403+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_set_display_callback"));
404+
405+
if (is_gsapi_set_arg_encoding_supported)
406+
{
407+
this.gsapi_set_arg_encoding = _crossPlatformLibrary.GetDelegateForFunction<gsapi_set_arg_encoding>("gsapi_set_arg_encoding");
408+
409+
if (this.gsapi_set_arg_encoding == null)
410+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_set_arg_encoding"));
411+
}
412+
413+
this.gsapi_init_with_args = _crossPlatformLibrary.GetDelegateForFunction<gsapi_init_with_args>("gsapi_init_with_args");
414+
415+
if (this.gsapi_init_with_args == null)
416+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_init_with_args"));
417+
418+
this.gsapi_run_string_begin = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_string_begin>("gsapi_run_string_begin");
419+
420+
if (this.gsapi_run_string_begin == null)
421+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string_begin"));
422+
423+
this.gsapi_run_string_continue = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_string_continue>("gsapi_run_string_continue");
424+
425+
if (this.gsapi_run_string_continue == null)
426+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string_continue"));
427+
428+
this.gsapi_run_string_end = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_string_end>("gsapi_run_string_end");
429+
430+
if (this.gsapi_run_string_end == null)
431+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string_end"));
432+
433+
this.gsapi_run_string_with_length = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_string_with_length>("gsapi_run_string_with_length");
434+
435+
if (this.gsapi_run_string_with_length == null)
436+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string_with_length"));
437+
438+
this.gsapi_run_string = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_string>("gsapi_run_string");
439+
440+
if (this.gsapi_run_string == null)
441+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string"));
442+
443+
this.gsapi_run_ptr_string = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_ptr_string>("gsapi_run_string");
444+
445+
if (this.gsapi_run_ptr_string == null)
446+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_string"));
447+
448+
this.gsapi_run_file = _crossPlatformLibrary.GetDelegateForFunction<gsapi_run_file>("gsapi_run_file");
449+
450+
if (this.gsapi_run_file == null)
451+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_run_file"));
452+
453+
this.gsapi_exit = _crossPlatformLibrary.GetDelegateForFunction<gsapi_exit>("gsapi_exit");
454+
455+
if (this.gsapi_exit == null)
456+
throw new GhostscriptException(string.Format(symbolMappingError, "gsapi_exit"));
313457
}
314458

315459
#endregion
316460

317461
#region ThrowIncompatibileNativeGhostscriptLibraryException
318462

319463
/// <summary>
320-
/// Throws friendly gsdll incompatibility message.
464+
/// Throws friendly library incompatibility message.
321465
/// </summary>
322466
private void ThrowIncompatibileNativeGhostscriptLibraryException()
323467
{
324-
throw new BadImageFormatException((Environment.Is64BitProcess ?
325-
"You are using native Ghostscript library (gsdll32.dll) compiled for 32bit systems in a 64bit process. You need to use gsdll64.dll. " +
326-
"64bit native Ghostscript library can be downloaded from http://www.ghostscript.com/download/gsdnld.html" :
327-
"You are using native Ghostscript library (gsdll64.dll) compiled for 64bit systems in a 32bit process. You need to use gsdll32.dll. " +
328-
"32bit native Ghostscript library can be downloaded from http://www.ghostscript.com/download/gsdnld.html"));
468+
string errorMessage = CrossPlatformNativeLibraryHelper.GetCompatibilityErrorMessage();
469+
throw new BadImageFormatException(errorMessage);
329470
}
330471

331472
#endregion

0 commit comments

Comments
 (0)