Commit d58cd33d authored by Mark Florisson's avatar Mark Florisson

Get rid of a lot of entry declarations + optional argument to not allocate buffer in cython.array

parent 06c02d31
...@@ -535,6 +535,7 @@ class GetAndReleaseBufferUtilityCode(object): ...@@ -535,6 +535,7 @@ class GetAndReleaseBufferUtilityCode(object):
# which has the right tp_flags set, but emulation otherwise. # which has the right tp_flags set, but emulation otherwise.
requires = None requires = None
is_cython_utility = False
def __init__(self): def __init__(self):
pass pass
......
...@@ -73,6 +73,7 @@ class CythonScope(ModuleScope): ...@@ -73,6 +73,7 @@ class CythonScope(ModuleScope):
# "end-users" but nobody will know it is there anyway... # "end-users" but nobody will know it is there anyway...
cython_testscope_utility_code.declare_in_scope(self) cython_testscope_utility_code.declare_in_scope(self)
cython_test_extclass_utility_code.declare_in_scope(self) cython_test_extclass_utility_code.declare_in_scope(self)
cython_array_utility_code.declare_in_scope(self)
# #
# The view sub-scope # The view sub-scope
...@@ -84,66 +85,7 @@ class CythonScope(ModuleScope): ...@@ -84,66 +85,7 @@ class CythonScope(ModuleScope):
cythonview_testscope_utility_code.declare_in_scope(viewscope) cythonview_testscope_utility_code.declare_in_scope(viewscope)
for x in ('strided', 'contig', 'follow', 'direct', 'ptr', 'full'): view_utility_code.declare_in_scope(viewscope)
entry = viewscope.declare_var(x, py_object_type, None,
cname='__pyx_viewaxis_%s' % x,
is_cdef=True)
entry.utility_code_definition = view_utility_code
#
# cython.view.memoryview declaration
#
self.memviewentry = entry = viewscope.declare_c_class(memview_name, None,
implementing=1,
objstruct_cname = memview_objstruct_cname,
typeobj_cname = memview_typeobj_cname,
typeptr_cname= memview_typeptr_cname)
entry.utility_code_definition = view_utility_code
#
# cython.array declaration
#
name = u'array'
entry = self.declare_c_class(name, None,
implementing=1,
objstruct_cname='__pyx_obj_array',
typeobj_cname='__pyx_tobj_array',
typeptr_cname=Naming.typeptr_prefix+name)
# NOTE: the typeptr_cname is constrained to be '__pyx_ptype_<name>'
# (name is 'array' in this case). otherwise the code generation for
# the struct pointers will not work!
entry.utility_code_definition = cython_array_utility_code
arr_scope = entry.type.scope
arr_scope.declare_var(u'data', c_char_ptr_type, None, is_cdef = 1)
arr_scope.declare_var(u'len', c_size_t_type, None, is_cdef = 1)
arr_scope.declare_var(u'format', c_char_ptr_type, None, is_cdef = 1)
arr_scope.declare_var(u'ndim', c_int_type, None, is_cdef = 1)
arr_scope.declare_var(u'shape', c_py_ssize_t_ptr_type, None, is_cdef = 1)
arr_scope.declare_var(u'strides', c_py_ssize_t_ptr_type, None, is_cdef = 1)
arr_scope.declare_var(u'itemsize', c_py_ssize_t_type, None, is_cdef = 1)
# declare the __getbuffer__ & __releasebuffer__ functions
for idx, name in enumerate(('__getbuffer__', '__releasebuffer__')):
entry = arr_scope.declare_pyfunction(name, None)
# FIXME XXX: hack right here!!!
entry.func_cname = '__pyx_pf_9__pyxutil_5array_%d' % (idx + 1) + name
entry.utility_code_definition = cython_array_utility_code
#
# Declare the array modes
#
entry = self.declare_var(u'PyBUF_C_CONTIGUOUS', c_int_type, None,
cname='PyBUF_C_CONTIGUOUS',is_cdef = 1)
entry = self.declare_var(u'PyBUF_F_CONTIGUOUS', c_int_type, None,
is_cdef = 1)
entry = self.declare_var(u'PyBUF_ANY_CONTIGUOUS', c_int_type, None,
is_cdef = 1)
def create_cython_scope(context, create_testscope): def create_cython_scope(context, create_testscope):
...@@ -167,9 +109,9 @@ cdef object _testscope(int value): ...@@ -167,9 +109,9 @@ cdef object _testscope(int value):
undecorated_methods_protos = UtilityCode(proto=u""" undecorated_methods_protos = UtilityCode(proto=u"""
/* These methods are undecorated and have therefore no prototype */ /* These methods are undecorated and have therefore no prototype */
static PyObject *__pyx_TestClass_cdef_method( static PyObject *__pyx_TestClass_cdef_method(
struct __pyx_TestClass *self, int value); struct __pyx_TestClass_obj *self, int value);
static PyObject *__pyx_TestClass_cpdef_method( static PyObject *__pyx_TestClass_cpdef_method(
struct __pyx_TestClass *self, int value, int skip_dispatch); struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
static PyObject *__pyx_TestClass_def_method( static PyObject *__pyx_TestClass_def_method(
PyObject *self, PyObject *value); PyObject *self, PyObject *value);
""") """)
...@@ -237,9 +179,8 @@ cdef object _testscope(int value): ...@@ -237,9 +179,8 @@ cdef object _testscope(int value):
""") """)
memview_name = u'memoryview' memview_name = u'memoryview'
memview_typeptr_cname = Naming.typeptr_prefix+memview_name memview_typeptr_cname = '__pyx_memoryview_type'
memview_typeobj_cname = '__pyx_tobj_'+memview_name memview_objstruct_cname = '__pyx_memoryview_obj'
memview_objstruct_cname = '__pyx_obj_'+memview_name
view_utility_code = CythonUtilityCode( view_utility_code = CythonUtilityCode(
u""" u"""
cdef class Enum(object): cdef class Enum(object):
...@@ -260,6 +201,7 @@ cdef extern from *: ...@@ -260,6 +201,7 @@ cdef extern from *:
int __Pyx_GetBuffer(object, Py_buffer *, int) int __Pyx_GetBuffer(object, Py_buffer *, int)
void __Pyx_ReleaseBuffer(Py_buffer *) void __Pyx_ReleaseBuffer(Py_buffer *)
@cname('__pyx_memoryview')
cdef class memoryview(object): cdef class memoryview(object):
cdef object obj cdef object obj
...@@ -274,13 +216,11 @@ cdef class memoryview(object): ...@@ -274,13 +216,11 @@ cdef class memoryview(object):
self.obj = None self.obj = None
__Pyx_ReleaseBuffer(&self.view) __Pyx_ReleaseBuffer(&self.view)
@cname('__pyx_memoryview_new')
cdef memoryview memoryview_cwrapper(object o, int flags): cdef memoryview memoryview_cwrapper(object o, int flags):
return memoryview(o, flags) return memoryview(o, flags)
""", name="view_code", """, name="view_code", requires=(Buffer.GetAndReleaseBufferUtilityCode(),))
prefix="__pyx_viewaxis_",
requires=(Buffer.GetAndReleaseBufferUtilityCode(),))
cyarray_prefix = u'__pyx_cythonarray_'
cython_array_utility_code = CythonUtilityCode(u''' cython_array_utility_code = CythonUtilityCode(u'''
cdef extern from "stdlib.h": cdef extern from "stdlib.h":
void *malloc(size_t) void *malloc(size_t)
...@@ -293,6 +233,7 @@ cdef extern from "Python.h": ...@@ -293,6 +233,7 @@ cdef extern from "Python.h":
PyBUF_F_CONTIGUOUS, PyBUF_F_CONTIGUOUS,
PyBUF_ANY_CONTIGUOUS PyBUF_ANY_CONTIGUOUS
@cname("__pyx_array")
cdef class array: cdef class array:
cdef: cdef:
...@@ -304,20 +245,22 @@ cdef class array: ...@@ -304,20 +245,22 @@ cdef class array:
Py_ssize_t *strides Py_ssize_t *strides
Py_ssize_t itemsize Py_ssize_t itemsize
str mode str mode
void (*callback_free_data)(char *data)
def __cinit__(array self, tuple shape, Py_ssize_t itemsize, char *format, mode="c"): def __cinit__(array self, tuple shape, Py_ssize_t itemsize, char *format,
mode="c", bint allocate_buffer=True):
self.ndim = len(shape) self.ndim = len(shape)
self.itemsize = itemsize self.itemsize = itemsize
if not self.ndim: if not self.ndim:
raise ValueError("Empty shape tuple for cython.array") raise ValueError("Empty shape tuple for cython.array")
if self.itemsize <= 0: if self.itemsize <= 0:
raise ValueError("itemsize <= 0 for cython.array") raise ValueError("itemsize <= 0 for cython.array")
self.format = format self.format = format
self.shape = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)*self.ndim) self.shape = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)*self.ndim)
self.strides = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)*self.ndim) self.strides = <Py_ssize_t *>malloc(sizeof(Py_ssize_t)*self.ndim)
...@@ -358,9 +301,14 @@ cdef class array: ...@@ -358,9 +301,14 @@ cdef class array:
self.mode = mode self.mode = mode
self.data = <char *>malloc(self.len) if allocate_buffer:
if not self.data: self.data = <char *>malloc(self.len)
raise MemoryError("unable to allocate array data.") if not self.data:
raise MemoryError("unable to allocate array data.")
else:
self.data = NULL
self.callback_free_data = NULL
def __getbuffer__(self, Py_buffer *info, int flags): def __getbuffer__(self, Py_buffer *info, int flags):
...@@ -383,13 +331,16 @@ cdef class array: ...@@ -383,13 +331,16 @@ cdef class array:
info.obj = None info.obj = None
def __releasebuffer__(array self, Py_buffer* info): def __releasebuffer__(array self, Py_buffer* info):
# array.__releasebuffer__ should not be called, # array.__releasebuffer__ should not be called,
# because the Py_buffer's 'obj' field is set to None. # because the Py_buffer's 'obj' field is set to None.
raise NotImplementedError() raise NotImplementedError()
def __dealloc__(array self): def __dealloc__(array self):
if self.data: if self.data:
free(self.data) if self.callback_free_data != NULL:
self.callback_free_data(self.data)
else:
free(self.data)
self.data = NULL self.data = NULL
if self.strides: if self.strides:
free(self.strides) free(self.strides)
...@@ -400,7 +351,7 @@ cdef class array: ...@@ -400,7 +351,7 @@ cdef class array:
self.format = NULL self.format = NULL
self.itemsize = 0 self.itemsize = 0
@cname("__pyx_array_new")
cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *mode): cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, char *mode):
return array(shape, itemsize, format, mode) return array(shape, itemsize, format, mode)
''')
''', prefix=cyarray_prefix)
...@@ -7630,9 +7630,8 @@ class CoerceToMemViewSliceNode(CoercionNode): ...@@ -7630,9 +7630,8 @@ class CoerceToMemViewSliceNode(CoercionNode):
import MemoryView, Buffer import MemoryView, Buffer
memviewobj = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True) memviewobj = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
buf_flag = MemoryView.get_buf_flag(self.type.axes) buf_flag = MemoryView.get_buf_flag(self.type.axes)
code.putln("%s = (PyObject *)" code.putln("%s = (PyObject *) __pyx_memoryview_new(%s, %s);" %
"__pyx_viewaxis_memoryview_cwrapper(%s, %s);" %\ (memviewobj, self.arg.py_result(), buf_flag))
(memviewobj, self.arg.py_result(), buf_flag))
code.putln(code.error_goto_if_PyErr(self.pos)) code.putln(code.error_goto_if_PyErr(self.pos))
ndim = len(self.type.axes) ndim = len(self.type.axes)
spec_int_arr = code.funcstate.allocate_temp( spec_int_arr = code.funcstate.allocate_temp(
...@@ -7658,7 +7657,7 @@ class CoerceToMemViewSliceNode(CoercionNode): ...@@ -7658,7 +7657,7 @@ class CoerceToMemViewSliceNode(CoercionNode):
else: else:
c_or_f_flag = "0" c_or_f_flag = "0"
code.putln(code.error_goto_if("-1 == __Pyx_ValidateAndInit_memviewslice(" code.putln(code.error_goto_if("-1 == __Pyx_ValidateAndInit_memviewslice("
"(struct __pyx_obj_memoryview *) %(memviewobj)s," "(struct __pyx_memoryview_obj *) %(memviewobj)s,"
" %(spec_int_arr)s, %(c_or_f_flag)s, %(ndim)d," " %(spec_int_arr)s, %(c_or_f_flag)s, %(ndim)d,"
" &%(dtype_typeinfo)s, __pyx_stack, &%(result)s)" % locals(), self.pos)) " &%(dtype_typeinfo)s, __pyx_stack, &%(result)s)" % locals(), self.pos))
code.putln("}") code.putln("}")
......
...@@ -378,7 +378,7 @@ static int %(cfunc_name)s(const __Pyx_memviewslice *from_mvs, __Pyx_memviewslice ...@@ -378,7 +378,7 @@ static int %(cfunc_name)s(const __Pyx_memviewslice *from_mvs, __Pyx_memviewslice
char *to_buf = (char *)to_mvs->data; char *to_buf = (char *)to_mvs->data;
char *from_buf = (char *)from_mvs->data; char *from_buf = (char *)from_mvs->data;
struct __pyx_obj_memoryview *temp_memview = 0; struct __pyx_memoryview_obj *temp_memview = 0;
char *temp_data = 0; char *temp_data = 0;
int ndim_idx = 0; int ndim_idx = 0;
...@@ -700,13 +700,13 @@ static __Pyx_memviewslice %(copy_name)s(const __Pyx_memviewslice from_mvs) { ...@@ -700,13 +700,13 @@ static __Pyx_memviewslice %(copy_name)s(const __Pyx_memviewslice from_mvs) {
__Pyx_RefNannyDeclarations __Pyx_RefNannyDeclarations
int i; int i;
__Pyx_memviewslice new_mvs = {0, 0}; __Pyx_memviewslice new_mvs = {0, 0};
struct __pyx_obj_memoryview *from_memview = from_mvs.memview; struct __pyx_memoryview_obj *from_memview = from_mvs.memview;
Py_buffer *buf = &from_memview->view; Py_buffer *buf = &from_memview->view;
PyObject *shape_tuple = 0; PyObject *shape_tuple = 0;
PyObject *temp_int = 0; PyObject *temp_int = 0;
struct __pyx_obj_array *array_obj = 0; struct __pyx_array_obj *array_obj = 0;
struct __pyx_obj_memoryview *memview_obj = 0; struct __pyx_memoryview_obj *memview_obj = 0;
char mode[] = "%(mode)s"; char *mode = "%(mode)s";
__Pyx_RefNannySetupContext("%(copy_name)s"); __Pyx_RefNannySetupContext("%(copy_name)s");
...@@ -726,13 +726,13 @@ static __Pyx_memviewslice %(copy_name)s(const __Pyx_memviewslice from_mvs) { ...@@ -726,13 +726,13 @@ static __Pyx_memviewslice %(copy_name)s(const __Pyx_memviewslice from_mvs) {
} }
} }
array_obj = __pyx_cythonarray_array_cwrapper(shape_tuple, %(sizeof_dtype)s, buf->format, mode); array_obj = __pyx_array_new(shape_tuple, %(sizeof_dtype)s, buf->format, mode);
if (unlikely(!array_obj)) { if (unlikely(!array_obj)) {
goto fail; goto fail;
} }
__Pyx_GOTREF(array_obj); __Pyx_GOTREF(array_obj);
memview_obj = __pyx_viewaxis_memoryview_cwrapper((PyObject *)array_obj, %(contig_flag)s); memview_obj = __pyx_memoryview_new((PyObject *) array_obj, %(contig_flag)s);
if (unlikely(!memview_obj)) { if (unlikely(!memview_obj)) {
goto fail; goto fail;
} }
...@@ -810,18 +810,18 @@ memviewslice_init_code = UtilityCode(proto="""\ ...@@ -810,18 +810,18 @@ memviewslice_init_code = UtilityCode(proto="""\
#define __Pyx_IS_C_CONTIG 1 #define __Pyx_IS_C_CONTIG 1
#define __Pyx_IS_F_CONTIG 2 #define __Pyx_IS_F_CONTIG 2
static int __Pyx_ValidateAndInit_memviewslice(struct __pyx_obj_memoryview *memview, static int __Pyx_ValidateAndInit_memviewslice(struct __pyx_memoryview_obj *memview,
int *axes_specs, int c_or_f_flag, int ndim, __Pyx_TypeInfo *dtype, int *axes_specs, int c_or_f_flag, int ndim, __Pyx_TypeInfo *dtype,
__Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice); __Pyx_BufFmt_StackElem stack[], __Pyx_memviewslice *memviewslice);
static int __Pyx_init_memviewslice( static int __Pyx_init_memviewslice(
struct __pyx_obj_memoryview *memview, struct __pyx_memoryview_obj *memview,
int ndim, int ndim,
__Pyx_memviewslice *memviewslice); __Pyx_memviewslice *memviewslice);
""" % {'BUF_MAX_NDIMS' :Options.buffer_max_dims}, """ % {'BUF_MAX_NDIMS' :Options.buffer_max_dims},
impl = """\ impl = """\
static int __Pyx_ValidateAndInit_memviewslice( static int __Pyx_ValidateAndInit_memviewslice(
struct __pyx_obj_memoryview *memview, struct __pyx_memoryview_obj *memview,
int *axes_specs, int *axes_specs,
int c_or_f_flag, int c_or_f_flag,
int ndim, int ndim,
...@@ -951,7 +951,7 @@ no_fail: ...@@ -951,7 +951,7 @@ no_fail:
} }
static int __Pyx_init_memviewslice( static int __Pyx_init_memviewslice(
struct __pyx_obj_memoryview *memview, struct __pyx_memoryview_obj *memview,
int ndim, int ndim,
__Pyx_memviewslice *memviewslice) { __Pyx_memviewslice *memviewslice) {
......
...@@ -6986,9 +6986,9 @@ class CnameDecoratorNode(StatNode): ...@@ -6986,9 +6986,9 @@ class CnameDecoratorNode(StatNode):
scope = self.node.scope scope = self.node.scope
e.cname = self.cname e.cname = self.cname
e.type.objstruct_cname = self.cname e.type.objstruct_cname = self.cname + '_obj'
e.type.typeobj_cname = Naming.typeobj_prefix + self.cname e.type.typeobj_cname = Naming.typeobj_prefix + self.cname
e.type.typeptr_cname = Naming.typeptr_prefix + self.cname e.type.typeptr_cname = self.cname + '_type'
e.as_variable.cname = py_object_type.cast_code(e.type.typeptr_cname) e.as_variable.cname = py_object_type.cast_code(e.type.typeptr_cname)
...@@ -7002,6 +7002,7 @@ class CnameDecoratorNode(StatNode): ...@@ -7002,6 +7002,7 @@ class CnameDecoratorNode(StatNode):
self.node.analyse_expressions(env) self.node.analyse_expressions(env)
def generate_function_definitions(self, env, code): def generate_function_definitions(self, env, code):
"Ensure a prototype for every @cname method in the right place"
if self.is_function and env.is_c_class_scope: if self.is_function and env.is_c_class_scope:
# method in cdef class, generate a prototype in the header # method in cdef class, generate a prototype in the header
h_code = code.globalstate['utility_code_proto'] h_code = code.globalstate['utility_code_proto']
......
...@@ -2075,7 +2075,7 @@ def is_memoryviewslice_access(s): ...@@ -2075,7 +2075,7 @@ def is_memoryviewslice_access(s):
if s.sy == ':': if s.sy == ':':
retval = True retval = True
for sv in reversed(saved): for sv in saved[::-1]:
s.put_back(*sv) s.put_back(*sv)
return retval return retval
......
...@@ -2690,8 +2690,8 @@ c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type) ...@@ -2690,8 +2690,8 @@ c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type)
c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct", c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct",
None, 1, "__Pyx_LocalBuf_ND") None, 1, "__Pyx_LocalBuf_ND")
cython_memoryview_type = CStructOrUnionType("__pyx_obj_memoryview", "struct", cython_memoryview_type = CStructOrUnionType("__pyx_memoryview_obj", "struct",
None, 0, "__pyx_obj_memoryview") None, 0, "__pyx_memoryview_obj")
cython_memoryview_ptr_type = CPtrType(cython_memoryview_type) cython_memoryview_ptr_type = CPtrType(cython_memoryview_type)
......
...@@ -51,8 +51,8 @@ class CythonUtilityCode(object): ...@@ -51,8 +51,8 @@ class CythonUtilityCode(object):
Functions decorated with @cname('c_func_name') get the given cname. Functions decorated with @cname('c_func_name') get the given cname.
For cdef classes the rules are as follows: For cdef classes the rules are as follows:
obj struct -> <cname> obj struct -> <cname>_obj
obj type ptr -> __pyx_ptype_<cname> obj type ptr -> <cname>_type
methods -> <class_cname>_<method_cname> methods -> <class_cname>_<method_cname>
For methods the cname decorator is optional, but without the decorator the For methods the cname decorator is optional, but without the decorator the
......
...@@ -5,13 +5,15 @@ from cython cimport TestClass, _testclass_new as TestClass_New ...@@ -5,13 +5,15 @@ from cython cimport TestClass, _testclass_new as TestClass_New
from cython cimport test_call, test_dep from cython cimport test_call, test_dep
from cython.view cimport _testscope as viewtester from cython.view cimport _testscope as viewtester
from cpython cimport PyObject
cdef extern from *: cdef extern from *:
# TestClass stuff # TestClass stuff
cdef struct __pyx_TestClass: cdef struct __pyx_TestClass_obj:
int value int value
# Type pointer # Type pointer
cdef __pyx_TestClass *TestClassType "__pyx_ptype___pyx_TestClass" cdef PyObject *TestClassType "__pyx_TestClass_type"
# This is a cdef function # This is a cdef function
cdef __pyx_TestClass_New(int) cdef __pyx_TestClass_New(int)
...@@ -50,14 +52,14 @@ def test_cdef_class_cython_utility(): ...@@ -50,14 +52,14 @@ def test_cdef_class_cython_utility():
TestClass(20) TestClass(20)
TestClass(50) TestClass(50)
""" """
cdef __pyx_TestClass *objstruct cdef __pyx_TestClass_obj *objstruct
obj = TestClass_New(7) obj = TestClass_New(7)
objstruct = <__pyx_TestClass *> obj objstruct = <__pyx_TestClass_obj *> obj
print objstruct.value print objstruct.value
obj = __pyx_TestClass_New(14) obj = __pyx_TestClass_New(14)
objstruct = <__pyx_TestClass *> obj objstruct = <__pyx_TestClass_obj *> obj
print objstruct.value print objstruct.value
print (<object> TestClassType)(20) print (<object> TestClassType)(20)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment