📜  Python|可疑编码的 C 字符串 |第一组

📅  最后修改于: 2022-05-13 01:54:18.845000             🧑  作者: Mango

Python|可疑编码的 C 字符串 |第一组

可以在 C 和Python之间转换字符串,反之亦然,但 C 编码具有可疑或未知的性质。假设给定的 C 数据应该是 UTF-8,但它没有被严格执行。因此,处理这种格式错误的数据非常重要,这样它就不会导致Python崩溃或破坏过程中的字符串数据。

代码#1:C 数据和说明问题的函数。
/* Some dubious string data (malformed UTF-8) */
const char* sdata = "Spicy Jalape\xc3\xb1o\xae";
int slen = 16;
/* Output character data */
void print_chars(char* s, int len)
{
    int n = 0;
    while (n < len) {
        printf("%2x ", (unsigned char)s[n]);
        n++;
    }
    printf("\n");
}

在上面的代码中,字符串sdata 包含格式错误的数据和 UTF-8 的混合。然而,如果用户在 C 中调用print_chars(sdata, slen) ,它可以正常工作。

现在假设想要将 sdata 的内容转换为Python字符串,并通过扩展进一步将该字符串传递给print_chars()函数。下面给出的代码显示了即使存在编码问题也能准确保留原始数据的方式。

代码#2:

/* Return the C string back to Python */
static PyObject *py_retstr(PyObject *self, PyObject *args)
{
    if (!PyArg_ParseTuple(args, ""))
    {
        return NULL;
    }
    return PyUnicode_Decode(sdata, slen, "utf-8", "surrogateescape");
}
  
/* Wrapper for the print_chars() function */
static PyObject *py_print_chars(PyObject *self, PyObject *args)
{
    PyObject *obj, *bytes;
    char *s = 0;
    Py_ssize_t len;
    if (!PyArg_ParseTuple(args, "U", &obj))
    {
        return NULL;
    }
    if ((bytes = PyUnicode_AsEncodedString(obj,
    "utf-8","surrogateescape"))
            == NULL)
    {
        return NULL;
    }
    PyBytes_AsStringAndSize(bytes, &s, &len);
    print_chars(s, len);
    Py_DECREF(bytes);
    Py_RETURN_NONE;
}

代码#3:使用上面的代码 2

s = retstr()
printf (s)
  
printf ("\n", print_chars(s))
'Spicy Jalapeño\udcae'

53 70 69 63 79 20 4a 61 6c 61 70 65 c3 b1 6f ae

在这里,可以看到格式错误的字符串被编码为Python字符串而没有错误,并且当传递回 C 时,它又变成了与原始 C字符串完全相同的字节编码的字节字符串。