From 31b438e20b631aea2b87f3cba1c18782fe30470f Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 11 Sep 2009 22:59:36 +0200 Subject: [PATCH] support conversion between Python byte strings and unsigned char* --- Cython/Compiler/ExprNodes.py | 5 ++++- Cython/Compiler/PyrexTypes.py | 18 ++++++++++++++++++ ...unsigned_char_ptr_bytes_conversion_T359.pyx | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index abf575ab..2b0de0eb 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -928,7 +928,10 @@ class StringNode(ConstNode): if dst_type == PyrexTypes.c_char_ptr_type: self.type = PyrexTypes.c_char_ptr_type return self - + elif dst_type == PyrexTypes.c_uchar_ptr_type: + self.type = PyrexTypes.c_char_ptr_type + return CastNode(self, PyrexTypes.c_uchar_ptr_type) + if dst_type.is_int: if not self.type.is_pyobject and len(self.entry.init) == 1: return CharNode(self.pos, value=self.value) diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index dd43f0a6..8a69174b 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -1537,6 +1537,18 @@ class CCharPtrType(CStringType, CPtrType): CPtrType.__init__(self, c_char_type) +class CUCharPtrType(CStringType, CPtrType): + # C 'unsigned char *' type. + + pymemberdef_typecode = "T_STRING" + + to_py_function = "__Pyx_PyBytes_FromUString" + from_py_function = "__Pyx_PyBytes_AsUString" + + def __init__(self): + CPtrType.__init__(self, c_uchar_type) + + class UnspecifiedType(PyrexType): # Used as a placeholder until the type can be determined. @@ -1624,6 +1636,7 @@ c_double_complex_type = CComplexType(c_double_type) c_null_ptr_type = CNullPtrType(c_void_type) c_char_array_type = CCharArrayType(None) c_char_ptr_type = CCharPtrType() +c_uchar_ptr_type = CUCharPtrType() c_utf8_char_array_type = CUTF8CharArrayType(None) c_char_ptr_ptr_type = CPtrType(c_char_ptr_type) c_int_ptr_type = CPtrType(c_int_type) @@ -1768,6 +1781,8 @@ def c_ptr_type(base_type): # Construct a C pointer type. if base_type is c_char_type: return c_char_ptr_type + elif base_type is c_uchar_type: + return c_uchar_ptr_type elif base_type is error_type: return error_type else: @@ -1817,6 +1832,9 @@ type_conversion_predeclarations = """ #define __Pyx_PyBytes_AsString PyBytes_AsString #endif +#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((char*)s) +#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) __Pyx_PyBytes_AsString(s)) + #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) static INLINE int __Pyx_PyObject_IsTrue(PyObject*); static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); diff --git a/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx b/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx new file mode 100644 index 00000000..f525c905 --- /dev/null +++ b/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx @@ -0,0 +1,18 @@ +__doc__ = u""" +>>> py_string1.decode('ASCII') == 'test toast taste' +True +>>> py_string1 == py_string2 == py_string3 +True +""" + +cdef unsigned char* some_c_unstring = 'test toast taste' + +py_string1 = some_c_unstring + +cdef unsigned char* c_unstring_from_py = py_string1 + +py_string2 = c_unstring_from_py + +cdef char* c_string_from_py = py_string2 + +py_string3 = c_string_from_py -- 2.26.2