code: # Collection of supporting functions for wrapper functions
  __author__ = 'AndrewAnnex'
  from ctypes import c_char_p, c_bool, c_int, c_double, c_char, c_void_p, sizeof, \
      POINTER, pointer, Array, create_string_buffer, create_unicode_buffer, cast, Structure, \
      CFUNCTYPE, string_at
  
  import numpy
  from numpy import ctypeslib as numpc
  import six
  
  errorformat = """
  ================================================================================
  
  Toolkit version: {tkvsn}
  
  {short} --
  {explain}
  {long}
  
  {traceback}
  
  ================================================================================\
  """
  
  class SpiceyError(Exception):
      """
      SpiceyError wraps CSPICE errors.
      :type value: str
      """
      def __init__(self, value):
          self.value = value
  
      def __str__(self):
          return self.value
  
  
  def toDoubleVector(x):
      return DoubleArray.from_param(param=x)
  
  
  def toDoubleMatrix(x):
      return DoubleMatrix.from_param(param=x)
  
  
  def toIntVector(x):
      return IntArray.from_param(param=x)
  
  
  def toBoolVector(x):
      return BoolArray.from_param(param=x)
  
  
  def toPythonString(inString):
      if six.PY2:
          if isinstance(inString, c_char_p):
              return toPythonString(inString.value)
          return string_at(inString)
      elif six.PY3:
          if isinstance(inString, c_char_p):
              return toPythonString(inString.value)
          return bytes.decode(string_at(inString))
  
  
  def listtocharvector(x):
      assert (isinstance(x, list))
      return (c_char_p * len(x))(*[stringToCharP(y) for y in x])
  
  
  def charvector(ndim=1, lenvals=10):
      return ((c_char * lenvals) * ndim)()
  
  
  def listtodoublematrix(data, x=3, y=3):
      matrix = ((c_double * x) * y)()
      for i, row in enumerate(data):
          matrix[i] = tuple(row)
      return matrix
  
  
  def emptyCharArray(xLen=None, yLen=None):
      if not yLen:
          yLen = 1
      if not xLen:
          xLen = 1
      if isinstance(xLen, c_int):
          xLen = xLen.value
      if isinstance(yLen, c_int):
          yLen = yLen.value
      return ((c_char * xLen) * yLen)()
  
  
  def emptyDoubleMatrix(x=3, y=3):
      return ((c_double * x) * y)()
  
  
  def emptyDoubleVector(n):
      if isinstance(n, c_int):
          n = n.value
      assert(isinstance(n, int))
      return (c_double * n)()
  
  
  def emptyIntVector(n):
      if isinstance(n, c_int):
          n = n.value
      assert (isinstance(n, int))
      return (c_int * n)()
  
  
  def vectorToList(x):
      if isinstance(x[0], bool):
          return numpy.fromiter(x, numpy.bool, count=len(x))
      elif isinstance(x[0], int):
          return numpy.fromiter(x, numpy.int_, count=len(x))
      elif isinstance(x[0], float):
          return numpy.fromiter(x, numpy.float64, count=len(x))
      elif isinstance(x[0].value, bytes):
          return [toPythonString(y) for y in x]
  
  
  def matrixToList(x):
      return numpc.as_array(x)
  
  
  def stringToCharP(inobject, inlen=None):
  
      """
      :param inobject: input string, int for getting null string of length of int
      :param inlen: optional parameter, length of a given string can be specified
      :return:
      """
      if inlen and isinstance(inobject, str):
          return create_string_buffer(inobject.encode(encoding='UTF-8'), inlen)
      if isinstance(inobject, bytes):
          return inobject
      if isinstance(inobject, c_int):
          return stringToCharP(" " * inobject.value)
      if isinstance(inobject, int):
          return stringToCharP(" " * inobject)
      return c_char_p(inobject.encode(encoding='UTF-8'))
  
  
  def listToCharArray(inList, xLen=None, yLen=None):
      assert (isinstance(inList, list))
      if not yLen:
          yLen = len(inList)
      if not xLen:
          xLen = max(len(s) for s in inList) + 1
      if isinstance(xLen, c_int):
          xLen = xLen.value
      if isinstance(yLen, c_int):
          yLen = yLen.value
      return ((c_char * xLen) * yLen)(*[stringToCharP(l, inlen=xLen) for l in inList])
  
  
  def listToCharArrayPtr(inList, xLen=None, yLen=None):
      assert (isinstance(inList, list))
      if not yLen:
          yLen = len(inList)
      if not xLen:
          xLen = max(len(s) for s in inList) + 1
      if isinstance(xLen, c_int):
          xLen = xLen.value
      if isinstance(yLen, c_int):
          yLen = yLen.value
      return cast(((c_char * xLen) * yLen)(*[stringToCharP(l, inlen=xLen) for l in inList]), c_char_p)
  
  
  class DoubleArrayType:
      # Class type that will handle all double vectors, inspiration from python cookbook 3rd edition
      def from_param(self, param):
          typename = type(param).__name__
          if hasattr(self, 'from_' + typename):
              return getattr(self, 'from_' + typename)(param)
          elif isinstance(param, Array):
              return param
          else:
              raise TypeError("Can't convert %s" % typename)
  
      # Cast from lists/tuples
      def from_list(self, param):
          val = ((c_double) * len(param))(*param)
          return val
  
      # Cast from Tuple
      def from_tuple(self, param):
          val = ((c_double) * len(param))(*param)
          return val
  
      # Cast from a numpy array,
      def from_ndarray(self, param):
          # return param.data_as(POINTER(c_double))
          # the above older method does not work with functions which take vectors of known size
          return numpy.ctypeslib.as_ctypes(param)
  
      # Cast from array.array objects
      def from_array(self, param):
          if param.typecode != 'd':
              raise TypeError('must be an array of doubles')
          ptr, _ = param.buffer_info()
          return cast(ptr, POINTER(c_double))
  
  
  class DoubleMatrixType:
      # Class type that will handle all double matricies, inspiration from python cookbook 3rd edition
      def from_param(self, param):
          typename = type(param).__name__
          if hasattr(self, 'from_' + typename):
              return getattr(self, 'from_' + typename)(param)
          elif isinstance(param, Array):
              return param
          else:
              raise TypeError("Can't convert %s" % typename)
  
      # Cast from lists/tuples
      def from_list(self, param):
          val = ((c_double * len(param[0])) * len(param))(*[DoubleArray.from_param(x) for x in param])
          return val
  
      # Cast from Tuple
      def from_tuple(self, param):
          val = ((c_double * len(param[0])) * len(param))(*[DoubleArray.from_param(x) for x in param])
          return val
  
      # Cast from a numpy array
      def from_ndarray(self, param):
          #return param.data_as(POINTER(c_double))
          return numpy.ctypeslib.as_ctypes(param)
  
      # Cast from a numpy matrix
      def from_matrix(self, param):
          #return param.data_as(POINTER(c_double))
          return numpy.ctypeslib.as_ctypes(param)
  
  
  class IntArrayType:
      # Class type that will handle all int vectors, inspiration from python cookbook 3rd edition
      def from_param(self, param):
          typename = type(param).__name__
          if hasattr(self, 'from_' + typename):
              return getattr(self, 'from_' + typename)(param)
          elif isinstance(param, Array):
              return param
          else:
              raise TypeError("Can't convert %s" % typename)
  
      # Cast from lists/tuples
      def from_list(self, param):
          val = ((c_int) * len(param))(*param)
          return val
  
      # Cast from Tuple
      def from_tuple(self, param):
          val = ((c_int) * len(param))(*param)
          return val
  
      # Cast from a numpy array
      def from_ndarray(self, param):
          #return param.data_as(POINTER(c_int)) # not sure if long is same as int, it should be..
          #return numpy.ctypeslib.as_ctypes(param)
          return self.from_param(param.tolist())
  
      # Cast from array.array objects
      def from_array(self, param):
          if param.typecode != 'i':
              raise TypeError('must be an array of ints')
          ptr, _ = param.buffer_info()
          return cast(ptr, POINTER(c_int))
  
  
  class BoolArrayType:
      # Class type that will handle all int vectors, inspiration from python cookbook 3rd edition
      def from_param(self, param):
          typename = type(param).__name__
          if hasattr(self, 'from_' + typename):
              return getattr(self, 'from_' + typename)(param)
          elif isinstance(param, Array):
              return param
          else:
              raise TypeError("Can't convert %s" % typename)
  
      # Cast from lists/tuples
      def from_list(self, param):
          val = ((c_bool) * len(param))(*param)
          return val
  
      # Cast from Tuple
      def from_tuple(self, param):
          val = ((c_bool) * len(param))(*param)
          return val
  
      # Cast from a numpy array
      def from_ndarray(self, param):
          #return param.data_as(POINTER(c_int)) # not sure if long is same as int, it should be..
          #return numpy.ctypeslib.as_ctypes(param)
          return self.from_param(param.tolist())
  
  
  DoubleArray = DoubleArrayType()
  
  IntArray = IntArrayType()
  
  BoolArray = BoolArrayType()
  
  DoubleMatrix = DoubleMatrixType()
  
  
  class Plane(Structure):
      _fields_ = [
          ('_normal', c_double * 3),
          ('_constant', c_double)
      ]
  
      @property
      def normal(self):
          return vectorToList(self._normal)
  
      @property
      def constant(self):
          return self._constant
  
      def __str__(self):
          return '<Plane: normal=%s; constant=%s>' % (', '.join([str(x) for x in self._normal]), self._constant)
  
  
  class Ellipse(Structure):
      _fields_ = [
          ('_center', c_double * 3),
          ('_semi_major', c_double * 3),
          ('_semi_minor', c_double * 3)
      ]
  
      @property
      def center(self):
          return vectorToList(self._center)
  
      @property
      def semi_major(self):
          return vectorToList(self._semi_major)
  
      @property
      def semi_minor(self):
          return vectorToList(self._semi_minor)
  
      def __str__(self):
          return '<SpiceEllipse: center = %s, semi_major = %s, semi_minor = %s>' % \
                 (self.center, self.semi_major, self.semi_minor)
  
  
  class DataType(object):
      SPICE_CHR = 0
      SPICE_DP = 1
      SPICE_INT = 2
      SPICE_TIME = 3
      SPICE_BOOL = 4
      CHR = 0
      DP = 1
      INT = 2
      TIME = 3
      BOOL = 4
  
      def __init__(self):
          pass
  
  
  class SpiceEKDataType(c_int):
      _fields_ = [
          ('SPICE_CHR', c_int(0)),
          ('SPICE_DP', c_int(1)),
          ('SPICE_INT', c_int(2)),
          ('SPICE_TIME', c_int(3)),
          ('SPICE_BOOL', c_int(4)),
      ]
  
  
  class SpiceEKExprClass(c_int):
      _fields_ = [
          ('SPICE_EK_EXP_COL', c_int(0)),
          ('SPICE_EK_EXP_FUNC', c_int(1)),
          ('SPICE_EK_EXP_EXPR', c_int(2))
      ]
  
  
  class SpiceEKAttDsc(Structure):
      _fields_ = [
          ('_cclass', c_int),
          ('_dtype', SpiceEKDataType),
          ('_strlen', c_int),
          ('_size', c_int),
          ('_indexd', c_bool),
          ('_nullok', c_bool)
      ]
  
      @property
      def cclass(self):
          return self._cclass
  
      @property
      def dtype(self):
          return self._dtype.value
  
      @property
      def strlen(self):
          return self._strlen
  
      @property
      def size(self):
          return self._size
  
      @property
      def indexd(self):
          return self._indexd
  
      @property
      def nullok(self):
          return self._nullok
  
      def __str__(self):
          return '<SpiceEKAttDsc cclass = %s, dtype = %s, strlen = %s, size = %s, indexd = %s, nullok = %s >' % \
                 (self.cclass, self.dtype, self.strlen, self.size, self.indexd, self.nullok)
  
  
  class SpiceEKSegSum(Structure):
      _fields_ = [
          ('_tabnam', c_char * 65),
          ('_nrows', c_int),
          ('_ncols', c_int),
          ('_cnames', (c_char * 100) * 33),
          ('_cdescrs', SpiceEKAttDsc * 100)
      ]
  
      @property
      def tabnam(self):
          return toPythonString(self._tabnam)
  
      @property
      def nrows(self):
          return self._nrows
  
      @property
      def ncols(self):
          return self._ncols
  
      @property
      def cnames(self):
          return vectorToList(self._cnames)[0:self.ncols]
  
      @property
      def cdescrs(self):
          return self._cdescrs[0:self.ncols]
  
      def __str__(self):
          return '<SpiceEKSegSum tabnam = %s, nrows = %s, ncols = %s, cnames = %s, cdescrs = %s >' % (self.tabnam, self.nrows, self.ncols, self.cnames, self.cdescrs)
  
  
  #SpiceCell implementation below is inpart from github.com/DaRasch/spiceminer/
  # and modified as needed for this author, maybe we should work together?
  
  ### helper classes/functions ###
  BITSIZE = {'char': sizeof(c_char), 'int': sizeof(c_int), 'double': sizeof(c_double)}
  
  
  def _char_getter(data_p, index, length):
      return toPythonString((c_char * length).from_address(data_p + index * length * BITSIZE['char']))
  
  
  def _double_getter(data_p, index, length):
      return c_double.from_address(data_p + index * BITSIZE['double']).value
  
  
  def _int_getter(data_p, index, length):
      return c_int.from_address(data_p + index * BITSIZE['int']).value
  
  
  def SPICEDOUBLE_CELL(size):
      return SpiceCell.double(size)
  
  
  def SPICEINT_CELL(size):
      return SpiceCell.integer(size)
  
  
  def SPICECHAR_CELL(size, length):
      return SpiceCell.character(size, length)
  
  
  class SpiceCell(Structure):
      #Most written by DaRasch
      DATATYPES_ENUM = {'char': 0, 'double': 1, 'int': 2, 'time': 3, 'bool': 4}
      DATATYPES_GET = [_char_getter, _double_getter] + [_int_getter] * 3
      baseSize = 6
      minCharLen = 6
      CTRLBLOCK = 6
      _fields_ = [
          ('dtype', c_int),
          ('length', c_int),
          ('size', c_int),
          ('card', c_int),
          ('isSet', c_int),
          ('adjust', c_int),
          ('init', c_int),
          ('base', c_void_p),
          ('data', c_void_p)
      ]
  
      def __init__(self, dtype=None, length=None, size=None, card=None, isSet=None, base=None, data=None):
          super(SpiceCell, self).__init__()
          self.dtype = dtype
          self.length = length
          self.size = size
          self.card = card
          self.isSet = isSet
          self.adjust = 0  # Always False, because not implemented
          self.init = 0  # Always False, because this is the constructor
          self.base = base  # void pointer
          self.data = data
  
      def __str__(self):
          return '<SpiceCell dtype = %s, length = %s, size = %s, card = %s, isSet = %s, adjust = %s, init = %s, base = %s, data = %s>' % (self.dtype, self.length, self.size, self.card, self.isSet, self.adjust, self.init, self.base, self.data)
  
      def is_int(self):
          return self.dtype == 2
  
      def is_double(self):
          return self.dtype == 1
  
      def is_char(self):
          return self.dtype == 0
  
      def is_time(self):
          return self.dtype == 3
  
      def is_bool(self):
          return self.dtype == 4
  
      def is_set(self):
          return self.isSet == 1
  
      @classmethod
      def character(cls, size, length):
          base = (c_char * ((cls.CTRLBLOCK + size) * length))()
          data = (c_char * (size * length)).from_buffer(
              base, cls.CTRLBLOCK * BITSIZE['char'] * length)
          instance = cls(cls.DATATYPES_ENUM['char'], length, size, 0, 1,
                         cast(base, c_void_p),
                         cast(data, c_void_p))
          return instance
  
      @classmethod
      def integer(cls, size):
          base = (c_int * (cls.CTRLBLOCK + size))()
          data = (c_int * size).from_buffer(
              base, cls.CTRLBLOCK * BITSIZE['int'])
          instance = cls(cls.DATATYPES_ENUM['int'], 0, size, 0, 1,
                         cast(base, c_void_p),
                         cast(data, c_void_p))
          return instance
  
      @classmethod
      def double(cls, size):
          base = (c_double * (cls.CTRLBLOCK + size))()
          data = (c_double * size).from_buffer(
              base, cls.CTRLBLOCK * BITSIZE['double'])
          instance = cls(cls.DATATYPES_ENUM['double'], 0, size, 0, 1,
                         cast(base, c_void_p),
                         cast(data, c_void_p))
          return instance
  
      def __len__(self):
          return self.card
  
      def __iter__(self):
          getter = SpiceCell.DATATYPES_GET[self.dtype]
          length, card, data = self.length, self.card, self.data
          for i in range(card):
              yield (getter(data, i, length))
  
      def __contains__(self, key):
          return key in self.__iter__()
  
      def __getitem__(self, key):
          getter = SpiceCell.DATATYPES_GET[self.dtype]
          length, card, data = self.length, self.card, self.data
          if isinstance(key, slice):
              start, stop, step = key.start or 0, key.stop or -1, key.step or 1
              #TODO Typechecking
              if card == 0:
                  return []
              else:
                  return list(getter(data, i, length)
                              for i in range(start % card, stop % card + 1, step))
          if key in range(-card, card):
              return getter(data, key, length)
          elif not isinstance(key, int):
              msg = 'SpiceCell inices must be integers, not {}'.format(type(key))
              raise TypeError(msg)
          else:
              raise IndexError('SpiceCell index out of range')
  
      def reset(self):
          self.card = 0
          self.init = 0
apis: numpy.ctypeslib.as_ctypes numpy.ctypeslib.as_array