buffer.py 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import ctypes
  2. from ctypes import (byref, POINTER, pythonapi,
  3. c_int, c_char, c_char_p, c_void_p, py_object, c_ssize_t)
  4. from .info import PY2
  5. c_ssize_p = POINTER(c_ssize_t)
  6. PyObject_GetBuffer = pythonapi.PyObject_GetBuffer
  7. PyBuffer_Release = pythonapi.PyBuffer_Release
  8. PyBUF_SIMPLE = 0
  9. PyBUF_WRITABLE = 1
  10. class Py_buffer(ctypes.Structure):
  11. _fields_ = [
  12. ("buf", c_void_p),
  13. ("obj", py_object),
  14. ("len", c_ssize_t),
  15. ("itemsize", c_ssize_t),
  16. ("readonly", c_int),
  17. ("ndim", c_int),
  18. ("format", c_char_p),
  19. ("shape", c_ssize_p),
  20. ("strides", c_ssize_p),
  21. ("suboffsets", c_ssize_p),
  22. ("internal", c_void_p)
  23. ]
  24. if PY2:
  25. _fields_.insert(-1, ("smalltable", c_ssize_t * 2))
  26. @classmethod
  27. def get_from(cls, obj, flags=PyBUF_SIMPLE):
  28. buf = cls()
  29. PyObject_GetBuffer(py_object(obj), byref(buf), flags)
  30. return buf
  31. def release(self):
  32. PyBuffer_Release(byref(self))
  33. def get_buffer(obj, writable=False):
  34. buf = Py_buffer.get_from(obj, PyBUF_WRITABLE if writable else PyBUF_SIMPLE)
  35. try:
  36. buffer_type = c_char * buf.len
  37. return buffer_type.from_address(buf.buf)
  38. finally:
  39. buf.release()