From: Lisandro Dalcin Date: Sat, 7 Feb 2009 18:09:06 +0000 (-0300) Subject: make Cython understand 'size_t' as a native C type (ticket #207) X-Git-Tag: 0.11.rc~91 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=996f17aa2ccaa67b57778c783aab52ef55048a30;p=cython.git make Cython understand 'size_t' as a native C type (ticket #207) --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 847efacf..0999eeb3 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -3892,7 +3892,7 @@ class TypecastNode(NewTempExprNode): class SizeofNode(ExprNode): # Abstract base class for sizeof(x) expression nodes. - type = PyrexTypes.c_int_type + type = PyrexTypes.c_size_t_type def check_const(self): pass diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 21b94883..1ad4f736 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -1810,8 +1810,8 @@ def looking_at_dotted_name(s): return result else: return 0 - -basic_c_type_names = ("void", "char", "int", "float", "double", "Py_ssize_t", "bint") + +basic_c_type_names = ("void", "char", "int", "float", "double", "Py_ssize_t", "size_t", "bint") sign_and_longness_words = ("short", "long", "signed", "unsigned") diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 7f11935c..9d2fce4c 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -462,9 +462,9 @@ class CNumericType(CType): default_value = "0" parsetuple_formats = ( # rank -> format - "BHIkK????", # unsigned - "bhilL?fd?", # assumed signed - "bhilL?fd?", # explicitly signed + "BHIkK?????", # unsigned + "bhilL??fd?", # assumed signed + "bhilL??fd?", # explicitly signed ) sign_words = ("unsigned ", "", "signed ") @@ -594,6 +594,12 @@ class CPySSizeTType(CIntType): from_py_function = "__pyx_PyIndex_AsSsize_t" +class CSizeTType(CUIntType): + + to_py_function = "__pyx_PyInt_FromSize_t" + from_py_function = "__pyx_PyInt_AsSize_t" + + class CFloatType(CNumericType): is_float = 1 @@ -1153,9 +1159,10 @@ rank_to_type_name = ( "long", # 3 "PY_LONG_LONG", # 4 "Py_ssize_t", # 5 - "float", # 6 - "double", # 7 - "long double", # 8 + "size_t", # 6 + "float", # 7 + "double", # 8 + "long double", # 9 ) py_object_type = PyObjectType() @@ -1175,7 +1182,6 @@ c_short_type = CIntType(1, 1, "T_SHORT") c_int_type = CIntType(2, 1, "T_INT") c_long_type = CIntType(3, 1, "T_LONG") c_longlong_type = CLongLongType(4, 1, "T_LONGLONG") -c_py_ssize_t_type = CPySSizeTType(5, 1) c_bint_type = CBIntType(2, 1, "T_INT") c_schar_type = CIntType(0, 2, "T_CHAR") @@ -1184,17 +1190,21 @@ c_sint_type = CIntType(2, 2, "T_INT") c_slong_type = CIntType(3, 2, "T_LONG") c_slonglong_type = CLongLongType(4, 2, "T_LONGLONG") -c_float_type = CFloatType(6, "T_FLOAT") -c_double_type = CFloatType(7, "T_DOUBLE") -c_longdouble_type = CFloatType(8) +c_py_ssize_t_type = CPySSizeTType(5, 1) +c_size_t_type = CSizeTType(6, 1) + +c_float_type = CFloatType(7, "T_FLOAT") +c_double_type = CFloatType(8, "T_DOUBLE") +c_longdouble_type = CFloatType(9) c_null_ptr_type = CNullPtrType(c_void_type) c_char_array_type = CCharArrayType(None) c_char_ptr_type = CCharPtrType() c_utf8_char_array_type = CUTF8CharArrayType(None) 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_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type) +c_size_t_ptr_type = CPtrType(c_size_t_type) c_returncode_type = CIntType(2, 1, "T_INT", is_returncode = 1) @@ -1207,28 +1217,31 @@ c_py_buffer_ptr_type = CPtrType(c_py_buffer_type) error_type = ErrorType() unspecified_type = UnspecifiedType() -lowest_float_rank = 6 - sign_and_rank_to_type = { #(signed, rank) - (0, 0, ): c_uchar_type, + (0, 0): c_uchar_type, (0, 1): c_ushort_type, (0, 2): c_uint_type, - (0, 3): c_ulong_type, - (0, 4): c_ulonglong_type, - (0, 5): c_ulonglong_type, # I'm not sure about this. this should be for size_t Py_ssize_t + (0, 3): c_ulong_type, + (0, 4): c_ulonglong_type, + (0, 5): c_ulonglong_type, # XXX I'm not sure about this. + (1, 0): c_char_type, (1, 1): c_short_type, (1, 2): c_int_type, (1, 3): c_long_type, (1, 4): c_longlong_type, - (1, 5): c_py_ssize_t_type, (2, 0): c_schar_type, (2, 1): c_sshort_type, (2, 2): c_sint_type, (2, 3): c_slong_type, (2, 4): c_slonglong_type, + + (1, 5): c_py_ssize_t_type, (2, 5): c_py_ssize_t_type, + (0, 6): c_size_t_type, + (1, 6): c_size_t_type, + (1, 6): c_float_type, (1, 7): c_double_type, (1, 8): c_longdouble_type, @@ -1251,7 +1264,6 @@ modifiers_and_name_to_type = { (1, 0, "int"): c_int_type, (1, 1, "int"): c_long_type, (1, 2, "int"): c_longlong_type, - (1, 0, "Py_ssize_t"): c_py_ssize_t_type, (1, 0, "float"): c_float_type, (1, 0, "double"): c_double_type, (1, 1, "double"): c_longdouble_type, @@ -1262,7 +1274,11 @@ modifiers_and_name_to_type = { (2, 0, "int"): c_sint_type, (2, 1, "int"): c_slong_type, (2, 2, "int"): c_slonglong_type, + + (1, 0, "Py_ssize_t"): c_py_ssize_t_type, (2, 0, "Py_ssize_t"): c_py_ssize_t_type, + (0, 0, "size_t") : c_size_t_type, + (1, 0, "size_t") : c_size_t_type, (1, 0, "long"): c_long_type, (1, 0, "short"): c_short_type, @@ -1380,6 +1396,9 @@ static INLINE PY_LONG_LONG __pyx_PyInt_AsLongLong(PyObject* x); static INLINE unsigned PY_LONG_LONG __pyx_PyInt_AsUnsignedLongLong(PyObject* x); static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b); +static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t); +static INLINE size_t __pyx_PyInt_AsSize_t(PyObject*); + #define __pyx_PyInt_AsLong(x) (PyInt_CheckExact(x) ? PyInt_AS_LONG(x) : PyInt_AsLong(x)) #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) """ + type_conversion_predeclarations @@ -1396,6 +1415,31 @@ static INLINE Py_ssize_t __pyx_PyIndex_AsSsize_t(PyObject* b) { return ival; } +static INLINE PyObject * __pyx_PyInt_FromSize_t(size_t ival) { +#if PY_VERSION_HEX < 0x02050000 + if (ival <= (size_t)LONG_MAX) + return PyInt_FromLong((long)ival); + else { + unsigned char *bytes = (unsigned char *) &ival; + int one = 1; int little = (int)*(unsigned char*)&one; + return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); + } +#else + return PyInt_FromSize_t(ival); +#endif +} + +static INLINE size_t __pyx_PyInt_AsSize_t(PyObject* b) { + unsigned PY_LONG_LONG val = __pyx_PyInt_AsUnsignedLongLong(b); + if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { + return (size_t)-1; + } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { + PyErr_SetString(PyExc_OverflowError, "value too large to convert to size_t"); + return (size_t)-1; + } + return val; +} + static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { if (x == Py_True) return 1; else if ((x == Py_False) | (x == Py_None)) return 0; diff --git a/Cython/Includes/python2.5.pxd b/Cython/Includes/python2.5.pxd index f478a5d5..5d08db6d 100644 --- a/Cython/Includes/python2.5.pxd +++ b/Cython/Includes/python2.5.pxd @@ -14,9 +14,6 @@ # - Add unicode calls. # - Add setobject calls. -cdef extern from "sys/types.h": - ctypedef unsigned int size_t - cdef extern from "stdio.h": ctypedef struct FILE: pass diff --git a/Cython/Includes/python_mem.pxd b/Cython/Includes/python_mem.pxd index 02cf3972..6d7b8dac 100644 --- a/Cython/Includes/python_mem.pxd +++ b/Cython/Includes/python_mem.pxd @@ -1,6 +1,5 @@ cdef extern from "Python.h": - ctypedef unsigned long size_t - + ##################################################################### # 9.2 Memory Interface ##################################################################### diff --git a/Cython/Includes/stdlib.pxd b/Cython/Includes/stdlib.pxd index 3de3cb9e..6653b748 100644 --- a/Cython/Includes/stdlib.pxd +++ b/Cython/Includes/stdlib.pxd @@ -1,6 +1,5 @@ cdef extern from "stdlib.h": - ctypedef unsigned long size_t void free(void *ptr) void *malloc(size_t size) void *realloc(void *ptr, size_t size) diff --git a/tests/run/size_t.pyx b/tests/run/size_t.pyx new file mode 100644 index 00000000..55001e21 --- /dev/null +++ b/tests/run/size_t.pyx @@ -0,0 +1,23 @@ +__doc__ = u""" +>>> test(0) +0 +>>> test(1) +1 +>>> test(2) +2 +>>> str(test((1<<32)-1)) +'4294967295' + +>>> test(-1) #doctest: +ELLIPSIS +Traceback (most recent call last): + ... +OverflowError: ... + +>>> test(1<<128) #doctest: +ELLIPSIS +Traceback (most recent call last): + ... +OverflowError: ... +""" + +def test(size_t i): + return i