# Pyrex - Builtin Definitions
#
-from Symtab import BuiltinScope
+from Symtab import BuiltinScope, StructOrUnionScope
from TypeSlots import Signature
+import PyrexTypes
builtin_function_table = [
# name, args, return, C API func, py equiv = "*"
("values","O", "O", "PyDict_Values")]),
]
+builtin_structs_table = [
+ ('Py_buffer', 'Py_buffer',
+ [("buf", PyrexTypes.c_void_ptr_type),
+ ("len", PyrexTypes.c_py_ssize_t_type),
+ ("readonly", PyrexTypes.c_bint_type),
+ ("format", PyrexTypes.c_char_ptr_type),
+ ("ndim", PyrexTypes.c_int_type),
+ ("shape", PyrexTypes.c_py_ssize_t_ptr_type),
+ ("strides", PyrexTypes.c_py_ssize_t_ptr_type),
+ ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
+ ("itemsize", PyrexTypes.c_py_ssize_t_type),
+ ("internal", PyrexTypes.c_void_ptr_type),
+ ])
+]
+
getattr3_utility_code = ["""
static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
""","""
sig = Signature(args, ret)
the_type.scope.declare_cfunction(name, sig.function_type(), None, cname)
+def init_builtin_structs():
+ for name, cname, attribute_types in builtin_structs_table:
+ scope = StructOrUnionScope(name)
+ for attribute_name, attribute_type in attribute_types:
+ scope.declare_var(
+ attribute_name, attribute_type, None, attribute_name)
+ builtin_scope.declare_struct_or_union(
+ name, "struct", scope, 1, None, cname = cname)
+
def init_builtins():
init_builtin_funcs()
init_builtin_types()
+ init_builtin_structs()
global list_type, tuple_type, dict_type
list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type
dict_type = builtin_scope.lookup('dict').type
-
+
init_builtins()
code.putln(" #define Py_SIZE(ob) ((PyVarObject*)(ob))->ob_size)")
code.putln(" #define PyVarObject_HEAD_INIT(type, size) \\")
code.putln(" PyObject_HEAD_INIT(type) size,")
+ code.putln("")
+ code.putln(" typedef struct {")
+ code.putln(" void *buf;")
+ code.putln(" Py_ssize_t len;")
+ code.putln(" int readonly;")
+ code.putln(" const char *format;")
+ code.putln(" int ndim;")
+ code.putln(" Py_ssize_t *shape;")
+ code.putln(" Py_ssize_t *strides;")
+ code.putln(" Py_ssize_t *suboffsets;")
+ code.putln(" Py_ssize_t itemsize;")
+ code.putln(" void *internal;")
+ code.putln(" } Py_buffer;")
+ code.putln("")
+ code.putln(" #define PyBUF_SIMPLE 0")
+ code.putln(" #define PyBUF_WRITABLE 0x0001")
+ code.putln(" #define PyBUF_LOCK 0x0002")
+ code.putln(" #define PyBUF_FORMAT 0x0004")
+ code.putln(" #define PyBUF_ND 0x0008")
+ code.putln(" #define PyBUF_STRIDES (0x0010 | PyBUF_ND)")
+ code.putln(" #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)")
+ code.putln(" #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)")
+ code.putln(" #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)")
+ code.putln(" #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)")
code.putln("#endif")
code.put(builtin_module_name_utility_code[0])
def p_module(s, pxd, full_module_name):
s.add_type_name("object")
+ s.add_type_name("Py_buffer")
pos = s.position()
doc = p_doc_string(s)
if pxd:
c_utf8_char_array_type = CUTF8CharArrayType(None)
c_char_ptr_type = CCharPtrType()
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
+c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type)
c_int_ptr_type = CPtrType(c_int_type)
c_returncode_type = CIntType(2, 1, "T_INT", is_returncode = 1)
c_anon_enum_type = CAnonEnumType(-1, 1)
+# the Py_buffer type is defined in Builtin.py
+c_py_buffer_ptr_type = CPtrType(CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer"))
+
error_type = ErrorType()
lowest_float_rank = 6
# 'p' void *
# 'P' void **
# 'i' int
+ # 'b' bint
# 'I' int *
# 'l' long
# 'Z' Py_ssize_t
# 's' char *
# 'S' char **
# 'r' int used only to signal exception
+ # 'B' Py_buffer *
# '-' dummy 'self' argument (not used)
# '*' rest of args passed as generic Python
# arg tuple and kw dict (must be last
's': PyrexTypes.c_char_ptr_type,
'S': PyrexTypes.c_char_ptr_ptr_type,
'r': PyrexTypes.c_returncode_type,
+ 'B': PyrexTypes.c_py_buffer_ptr_type,
# 'T', '-' and '*' are handled otherwise
# and are not looked up in here
}
# is_initialised_dynamically Is initialised by code in the module init function
# flag Py_TPFLAGS_XXX value indicating presence of slot
# py3k Indicates presence of slot in Python 3
-
- def __init__(self, slot_name, dynamic = 0, flag = None, py3k = True):
+ # py2 Indicates presence of slot in Python 2
+
+ def __init__(self, slot_name, dynamic = 0, flag = None, py3k = True, py2 = True):
self.slot_name = slot_name
self.is_initialised_dynamically = dynamic
self.flag = flag
self.py3k = py3k
+ self.py2 = py2
def generate(self, scope, code):
if self.is_initialised_dynamically:
value = self.slot_code(scope)
flag = self.flag
py3k = self.py3k
+ py2 = self.py2
if not py3k:
code.putln("#if PY_MAJOR_VERSION < 3")
+ elif not py2:
+ code.putln("#if PY_MAJOR_VERSION >= 3")
if flag:
code.putln("#if (PY_MAJOR_VERSION >= 3) || (Py_TPFLAGS_DEFAULT & %s)" % flag)
code.putln("%s, /*%s*/" % (value, self.slot_name))
- if not py3k:
- code.putln("#endif")
if flag:
code.putln("#endif")
+ if not py3k or not py2:
+ code.putln("#endif")
# Some C implementations have trouble statically
# initialising a global with a pointer to an extern
# method_name string The __xxx__ name of the method
# default string or None Default value of the slot
- def __init__(self, signature, slot_name, method_name, default = None, flag = None, py3k=True):
- SlotDescriptor.__init__(self, slot_name, flag = flag, py3k = py3k)
+ def __init__(self, signature, slot_name, method_name, default = None, flag = None, py3k=True, py2=True):
+ SlotDescriptor.__init__(self, slot_name, flag = flag, py3k = py3k, py2=py2)
self.signature = signature
self.slot_name = slot_name
self.method_name = method_name
#
# slot_name string Member name of the slot in the type object
- def __init__(self, slot_name):
- SlotDescriptor.__init__(self, slot_name)
+ def __init__(self, slot_name, py2 = True):
+ SlotDescriptor.__init__(self, slot_name, py2 = py2)
def slot_code(self, scope):
return scope.mangle_internal(self.slot_name)
# alternative default value will be placed in the type
# slot.
- def __init__(self, slot_name, user_methods, default_value):
- InternalMethodSlot.__init__(self, slot_name)
+ def __init__(self, slot_name, user_methods, default_value, py2 = True):
+ InternalMethodSlot.__init__(self, slot_name, py2 = py2)
self.user_methods = user_methods
self.default_value = default_value
# typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
# typedef PyObject *(*allocfunc)(struct _typeobject *, int);
+getbufferproc = Signature("TBi", "r") # typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
+releasebufferproc = Signature("TB", "v") # typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
+
+
#------------------------------------------------------------------------------------------
#
# Signatures for accessor methods of properties.
MethodSlot(getwritebufferproc, "bf_getwritebuffer", "__getwritebuffer__", py3k = False),
MethodSlot(getsegcountproc, "bf_getsegcount", "__getsegcount__", py3k = False),
MethodSlot(getcharbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3k = False),
+
+ MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", flag = "Py_TPFLAGS_HAVE_NEWBUFFER"),
+ MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", flag = "Py_TPFLAGS_HAVE_NEWBUFFER"),
)
#------------------------------------------------------------------------------------------
--- /dev/null
+__doc__ = u"""
+>>> b1 = TestBuffer()
+>>> b2 = TestBufferRelease()
+"""
+
+import sys
+if sys.version_info[0] >= 3:
+ __doc__ += u"""
+>>> ms = memoryview(s)
+>>> ms.tobytes()
+bytearray(b'abcdefg')
+
+>>> m1 = memoryview(b1)
+>>> m1.tobytes()
+locking!
+bytearray(b'abcdefg')
+
+>>> m2 = memoryview(b2)
+>>> m2.tobytes()
+locking!
+unlocking!
+bytearray(b'abcdefg')
+
+>>> del m1
+>>> del m2
+releasing!
+"""
+
+s = "abcdefg"
+
+cdef class TestBuffer:
+ def __getbuffer__(self, Py_buffer* buffer, int flags):
+ if buffer is NULL:
+ print u"locking!"
+ return
+ buffer.buf = <char*>s
+ buffer.len = len(s)
+ buffer.readonly = 0
+ buffer.format = "B"
+ buffer.ndim = 0
+ buffer.shape = NULL
+ buffer.strides = NULL
+ buffer.suboffsets = NULL
+ buffer.itemsize = 1
+ buffer.internal = NULL
+
+cdef class TestBufferRelease(TestBuffer):
+ def __releasebuffer__(self, Py_buffer* buffer):
+ if buffer is NULL:
+ print u"unlocking!"
+ else:
+ print u"releasing!"