Si uno quiere un módulo de extensión que necesita pasar una string terminada en NULL a una biblioteca C. Veamos cómo hacerlo con la implementación de strings Unicode de Python. Las bibliotecas C tienen muchas funciones que operan en strings terminadas en NULL declaradas como type char *
.
El código que se proporciona a continuación tiene una función C que ilustraremos y probaremos el problema. La función C ( Código #1 ) simplemente imprime la representación hexadecimal de caracteres individuales para que las strings pasadas se puedan depurar fácilmente.
Código #1:
void print_chars(char *s) { while (*s) { printf("%2x ", (unsigned char) *s); s++; } printf("\n"); } print_chars("Hello");
Producción :
48 65 6c 6c 6f
Para llamar a dicha función C desde Python, hay pocas opciones. Lo primero es que: se puede restringir para operar solo en bytes usando el código de conversión «y» PyArg_ParseTuple()
como se muestra en el código a continuación.
Código #2:
static PyObject * py_print_chars(PyObject * self, PyObject * args) { char * s; if (! PyArg_ParseTuple(args, "y", &s)) { return NULL; } print_chars(s); Py_RETURN_NONE; }
Veamos cómo funciona la función resultante y cómo se rechazan los bytes con bytes NULL incrustados y strings Unicode.
Código #3:
print (print_chars(b'Hello World')) print ("\n", print_chars(b'Hello\x00World')) print ("\n", print_chars('Hello World'))
Producción :
48 65 6c 6c 6f 20 57 6f 72 6c 64 Traceback (most recent call last): File "", line 1, in TypeError: must be bytes without null bytes, not bytes Traceback (most recent call last): File "", line 1, in TypeError: 'str' does not support the buffer interface
Si desea pasar strings Unicode en su lugar, use el código de formato «s» PyArg_ParseTuple()
como se muestra a continuación.
Código #4:
static PyObject *py_print_chars(PyObject *self, PyObject *args) { char *s; if (!PyArg_ParseTuple(args, "s", &s)) { return NULL; } print_chars(s); Py_RETURN_NONE; }
El uso del código anterior ( código #4 ) convertirá automáticamente todas las strings a una codificación UTF-8 terminada en NULL. Como se muestra en el siguiente código.
Código #5:
print (print_chars('Hello World')) # UTF-8 encoding print ("\n", print_chars('Spicy Jalape\u00f1o')) print ("\n", print_chars('Hello\x00World')) print ("\n", print_chars(b'Hello World'))
Producción :
48 65 6c 6c 6f 20 57 6f 72 6c 64 53 70 69 63 79 20 4a 61 6c 61 70 65 c3 b1 6f Traceback (most recent call last): File "", line 1, in TypeError: must be str without null characters, not str Traceback (most recent call last): File "", line 1, in TypeError: must be str, not bytes
Si trabaja con a PyObject *
y no puede usar PyArg_ParseTuple()
, el siguiente código explica cómo verificar y extraer una char *
referencia adecuada, tanto de un objeto de bytes como de string.
Código #6: Conversión de bytes
// Some Python Object PyObject *obj; // Conversion from bytes { char *s; s = PyBytes_AsString(o); if (!s) { /* TypeError already raised */ return NULL; } print_chars(s); }
Código #7: Conversión a bytes UTF-8 de una string
{ PyObject *bytes; char *s; if (!PyUnicode_Check(obj)) { PyErr_SetString(PyExc_TypeError, "Expected string"); return NULL; } bytes = PyUnicode_AsUTF8String(obj); s = PyBytes_AsString(bytes); print_chars(s); Py_DECREF(bytes); }
Ambas conversiones de código garantizan datos terminados en NULL, pero no hay verificación de bytes NULL incrustados en otros lugares dentro de la string. Eso debe verificarse si es importante.
Nota: Hay una sobrecarga de memoria oculta asociada con el uso del código de formato «s» PyArg_ParseTuple()
que es fácil de pasar por alto. Al escribir un código que utiliza esta conversión, se crea una string UTF-8 y se adjunta de forma permanente al objeto de string original que, si contiene caracteres que no son ASCII, hace que el tamaño de la string aumente hasta que se recopile como basura.
Código #8:
import sys s = 'Spicy Jalape\u00f1o' print ("Size : ", sys.getsizeof(s)) # passing string print("\n", print_chars(s)) # increasing size print ("\nSize : ", sys.getsizeof(s))
Producción :
Size : 87 53 70 69 63 79 20 4a 61 6c 61 70 65 c3 b1 6f Size : 103
Publicación traducida automáticamente
Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA