2626
2727using System ;
2828using System . IO ;
29+ using System . Runtime . InteropServices ;
2930using Microsoft . WinAny . Interop ;
3031
3132namespace 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