Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (révision 81150) +++ Objects/unicodeobject.c (copie de travail) @@ -1168,11 +1168,40 @@ wchar_t *w, Py_ssize_t size) { +#ifndef HAVE_USABLE_WCHAR_T + register const Py_UNICODE *u; + register Py_ssize_t i; +#ifndef Py_UNICODE_WIDE + const wchar_t *orig_w; +#endif +#endif + if (unicode == NULL) { PyErr_BadInternalCall(); return -1; } +#if !defined(HAVE_USABLE_WCHAR_T) && !defined(Py_UNICODE_WIDE) + orig_w = w; + u = PyUnicode_AS_UNICODE(unicode); + i = 0; + while (i < PyUnicode_GET_SIZE(unicode) && size != 0) { + if (0xD800 <= u[0] && u[0] <= 0xDBFF + && 0xDC00 <= u[1] && u[1] <= 0xDFFF) + { + *w++ = (((u[0] & 0x3FF) << 10) | (u[1] & 0x3FF)) + 0x10000; + u += 2; + i += 2; + } else { + *w++ = *u++; + i++; + } + size--; + } + if (size != 0) + *w = L'\0'; + return w - orig_w; +#else /* If possible, try to copy the 0-termination as well */ if (size > PyUnicode_GET_SIZE(unicode)) size = PyUnicode_GET_SIZE(unicode) + 1; @@ -1180,19 +1209,16 @@ #ifdef HAVE_USABLE_WCHAR_T memcpy(w, unicode->str, size * sizeof(wchar_t)); #else - { - register Py_UNICODE *u; - register Py_ssize_t i; - u = PyUnicode_AS_UNICODE(unicode); - for (i = size; i > 0; i--) - *w++ = *u++; - } + u = PyUnicode_AS_UNICODE(unicode); + for (i = size; i > 0; i--) + *w++ = *u++; #endif if (size > PyUnicode_GET_SIZE(unicode)) return PyUnicode_GET_SIZE(unicode); else return size; +#endif } #endif Index: Lib/ctypes/test/test_strings.py =================================================================== --- Lib/ctypes/test/test_strings.py (révision 81150) +++ Lib/ctypes/test/test_strings.py (copie de travail) @@ -74,6 +74,13 @@ buf[1] = "Z" self.assertEqual(buf.value, "xZCD") + def test_nonbmp(self): + if sizeof(c_wchar) < 4: + self.skipTest("sizeof(wchar_t) is smaller than 4 bytes") + u = '\U0010abcd' + w = c_wchar(u) + self.assertEqual(w.value, u) + class StringTestCase(unittest.TestCase): def XX_test_basic_strings(self): cs = c_string("abcdef") Index: Modules/_ctypes/cfield.c =================================================================== --- Modules/_ctypes/cfield.c (révision 81150) +++ Modules/_ctypes/cfield.c (copie de travail) @@ -1217,6 +1217,7 @@ u_set(void *ptr, PyObject *value, Py_ssize_t size) { Py_ssize_t len; + wchar_t chars[2]; if (PyBytes_Check(value)) { value = PyUnicode_FromEncodedObject(value, _ctypes_conversion_encoding, @@ -1231,7 +1232,7 @@ } else Py_INCREF(value); - len = PyUnicode_GET_SIZE(value); + len = PyUnicode_AsWideChar((PyUnicodeObject *)value, chars, 2); if (len != 1) { Py_DECREF(value); PyErr_SetString(PyExc_TypeError, @@ -1239,7 +1240,7 @@ return NULL; } - *(wchar_t *)ptr = PyUnicode_AS_UNICODE(value)[0]; + *(wchar_t *)ptr = chars[0]; Py_DECREF(value); _RET(value);