Source

yuureinohebi / libgs.py

Full commit
#!/usr/bin/env python3
import ctypes
from ctypes import c_char_p, c_long, c_int, c_uint, c_void_p, pointer, POINTER, CFUNCTYPE, sizeof
from ctypes.util import find_library

class gsapi_revision_t(ctypes.Structure):
    _fields_ = [('product', c_char_p),
            ('copyright', c_char_p),
            ('revision', c_long),
            ('revisiondate', c_long)]

c_stdstream_t = CFUNCTYPE(c_int, c_void_p, c_char_p, c_int)
c_poll_t = CFUNCTYPE(POINTER(c_int), c_void_p)

libgs = ctypes.CDLL(find_library('gs'))
libgs.gsapi_revision.argtypes = (POINTER(gsapi_revision_t), c_int)
libgs.gsapi_revision.restype = c_int
libgs.gsapi_new_instance.argtypes = (POINTER(c_void_p), c_void_p)
libgs.gsapi_new_instance.restype = c_int
libgs.gsapi_delete_instance.argtypes = (c_void_p,)
libgs.gsapi_delete_instance.restype = None
libgs.gsapi_set_stdio.argtypes = (c_void_p, c_stdstream_t, c_stdstream_t, c_stdstream_t)
libgs.gsapi_set_stdio.restype = c_int
libgs.gsapi_set_poll.restype = c_int
libgs.gsapi_set_poll.restype = c_int
#libgs.gsapi_set_display_callback.argtypes = ()
libgs.gsapi_set_display_callback.restype = c_int
libgs.gsapi_init_with_args.argtypes = (c_void_p, c_int, POINTER(c_char_p))
libgs.gsapi_init_with_args.restype = c_int
libgs.gsapi_run_string_begin.argtypes = (c_void_p, c_int, POINTER(c_int))
libgs.gsapi_run_string_begin.restype = c_int
libgs.gsapi_run_string_continue.argtypes = (c_void_p, c_char_p, c_uint, c_int, POINTER(c_int))
libgs.gsapi_run_string_continue.restype = c_int
libgs.gsapi_run_string_end.argtypes = (c_void_p, c_int, POINTER(c_int))
libgs.gsapi_run_string_end.restype = c_int
libgs.gsapi_run_string_with_length.argtypes = (c_void_p, c_char_p, c_uint, c_int, POINTER(c_int))
libgs.gsapi_run_string_with_length.restype = c_int
libgs.gsapi_run_string.argtypes = (c_void_p, c_char_p, c_int, POINTER(c_int))
libgs.gsapi_run_string.restype = c_int
libgs.gsapi_run_file.argtypes = (c_void_p, c_char_p, c_int, POINTER(c_int))
libgs.gsapi_run_string.restype = c_int
libgs.gsapi_exit.argtypes = (c_void_p,)
libgs.gsapi_exit.restype = c_int
#libgs.gsapi_set_visual_tracer.argtypes = ()
libgs.gsapi_set_visual_tracer.restype = c_int


class GhostscriptException(Exception):
    """Thrown when the interpreter breaks somehow"""

def gsapi_revision():
    r = gsapi_revision_t()
    libgs.gsapi_revision(pointer(r), sizeof(r))
    return r

def gsapi_new_instance():
    minst = c_void_p()
    if libgs.gsapi_new_instance(pointer(minst), None) != 0:
        raise GhostscriptException(
            'Ghostscript instance creation failed, supports only one at a time')
    return minst

def gsapi_init_with_args(instance, argv):
    argc = len(argv)
    argv_t = c_char_p * argc
    c_argv = argv_t(*argv)
    if libgs.gsapi_init_with_args(instance, argc, c_argv) != 0:
        raise GhostScriptException(
            'Initialization of instance failed')

gsapi_set_stdio = libgs.gsapi_set_stdio
gsapi_run_string_begin = libgs.gsapi_run_string_begin
gsapi_run_string_continue = libgs.gsapi_run_string_continue
gsapi_run_string_end = libgs.gsapi_run_string_end
gsapi_delete_instance = libgs.gsapi_delete_instance
gsapi_exit = libgs.gsapi_exit

def main():
    r = gsapi_revision()
    print(r.product, r.copyright, r.revision, r.revisiondate)
    gs = gsapi_new_instance()
    print(gs)
    print(gsapi_init_with_args(gs,
            ['ps2pdf', '-dNOPAUSE', '-dBATCH', '-sDEVICE=pdfwrite',
            '-sOutputFile=out.pdf', 'in.ps']))
    print(gsapi_exit(gs))
    print(gsapi_delete_instance(gs))

if __name__ == '__main__':
    main()