Skip to content

Instantly share code, notes, and snippets.

@Wirtos
Last active January 19, 2022 19:49
Show Gist options
  • Select an option

  • Save Wirtos/b9e0554e807109e6be14b136a5e737f2 to your computer and use it in GitHub Desktop.

Select an option

Save Wirtos/b9e0554e807109e6be14b136a5e737f2 to your computer and use it in GitHub Desktop.
short example on how you can use libtguy from python while retaining the "pythonic" style
import sys
from ctypes import c_void_p, c_char_p, c_size_t, c_uint, POINTER, CDLL, create_string_buffer, Structure
from typing import Sequence, Union
# ###########TYPES#####################################################
class TGStrView(Structure):
_fields_ = [('str', c_char_p), ('len', c_size_t)]
def __repr__(self):
return '({0}, {1})'.format(self.str, self.len)
TrashGuyState = c_void_p
FILE_p = c_void_p
# ###########LIBS######################################################
libtguy = CDLL("./libtguy." + {"linux": "so", "win32": "dll", "darwin": "dylyb"}.get(sys.platform, "so"))
# ###########FUNCTIONS#################################################
tguy_from_utf8 = libtguy.tguy_from_utf8
tguy_from_utf8.restype = TrashGuyState
tguy_from_utf8.argtypes = (c_char_p, c_size_t, c_uint)
tguy_from_arr = libtguy.tguy_from_arr
tguy_from_arr.restype = TrashGuyState
tguy_from_arr.argtypes = (POINTER(TGStrView), c_size_t, c_uint)
tguy_free = libtguy.tguy_free
tguy_free.restype = None
tguy_free.argtypes = (TrashGuyState,)
tguy_set_frame = libtguy.tguy_set_frame
tguy_set_frame.restype = None
tguy_set_frame.argtypes = (TrashGuyState, c_uint)
tguy_fprint = libtguy.tguy_fprint
tguy_fprint.restype = None
tguy_fprint.argtypes = (TrashGuyState, FILE_p)
tguy_print = libtguy.tguy_print
tguy_print.restype = None
tguy_print.argtypes = (TrashGuyState,)
tguy_bprint = libtguy.tguy_bprint
tguy_bprint.restype = None
tguy_bprint.argtypes = (TrashGuyState, c_char_p)
tguy_get_bsize = libtguy.tguy_get_bsize
tguy_get_bsize.restype = c_size_t
tguy_get_bsize.argtypes = (TrashGuyState,)
tguy_get_frames_count = libtguy.tguy_get_frames_count
tguy_get_frames_count.restype = c_uint
tguy_get_frames_count.argtypes = (TrashGuyState,)
tguy_get_arr = libtguy.tguy_get_arr
tguy_get_arr.restype = POINTER(TGStrView)
tguy_get_arr.argtypes = (TrashGuyState, POINTER(c_size_t))
# ####################################################################
class TGuy:
def __init__(self, string: Union[str, Sequence[str]], spacing: int = 4):
if isinstance(string, str):
# must be kept in self because passed c_char_p still points here after __init__ returns
self._keep = string.encode("utf-8")
self._tguy_obj = tguy_from_utf8(self._keep, len(self._keep), spacing)
else:
self._keep = (TGStrView * len(string))()
for i, sval in enumerate(string):
tmp = sval.encode("utf-8")
self._keep[i].str = tmp
self._keep[i].len = len(tmp)
self._tguy_obj = tguy_from_arr(self._keep, len(string), spacing)
if self._tguy_obj is None:
raise MemoryError
self._buf = create_string_buffer(tguy_get_bsize(self._tguy_obj))
self.max_frames = tguy_get_frames_count(self._tguy_obj)
def from_frame(self, i: int):
if not (0 <= i < self.max_frames):
raise IndexError("Bad index value: {}".format(i))
tguy_set_frame(self._tguy_obj, i)
def __del__(self):
tguy_free(self._tguy_obj)
def __pos__(self):
return self._tguy_obj
def __str__(self):
tguy_bprint(self._tguy_obj, self._buf)
return self._buf.value.decode("utf-8")
def __iter__(self):
for i in range(self.max_frames):
self.from_frame(i)
yield str(self)
def __getitem__(self, item):
self.from_frame(int(item))
return str(self)
def __int__(self):
return self.max_frames
def __index__(self):
return int(self)
def __sub__(self, other):
return int(self) - int(other)
tg = TGuy("юнікод")
for i in range(tg):
print(tg[i])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment