support conversion between Python byte strings and unsigned char*
authorStefan Behnel <scoder@users.berlios.de>
Fri, 11 Sep 2009 20:59:36 +0000 (22:59 +0200)
committerStefan Behnel <scoder@users.berlios.de>
Fri, 11 Sep 2009 20:59:36 +0000 (22:59 +0200)
Cython/Compiler/ExprNodes.py
Cython/Compiler/PyrexTypes.py
tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx [new file with mode: 0644]

index abf575ab6b2e1fe3b3528a5f09759012b8c8e77c..2b0de0eb1719ada1bd534570ab459825ef1b34bb 100644 (file)
@@ -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)
index dd43f0a6e9ee40ef5db4983d68925548457db9fc..8a69174b57276c74906753a83d4257506794d13f 100644 (file)
@@ -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 (file)
index 0000000..f525c90
--- /dev/null
@@ -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