Strings Unicode que pasan a bibliotecas C

Dado que uno quiere escribir un módulo de extensión que necesita pasar una string de Python a la función de biblioteca C. Entonces, surge la pregunta de manejar correctamente Unicode. Entonces, uno de los principales problemas que surgen es que las bibliotecas C existentes no entenderán la representación nativa de Unicode de Python. Por lo tanto, el principal desafío es convertir la string de Python en una forma que las bibliotecas C puedan entender más fácilmente.

Para ilustrar la solución, a continuación se muestran dos funciones de C que operan en datos de string y los generan para depuración y experimentación.

Código #1: Usa los bytes provistos en el formulariochar *, int

void print_chars(char *s, int len)
{
    int n = 0;
    while (n < len)
    {
        printf("%2x ", (unsigned char) s[n]);
        n++;
    }
    printf("\n");
}

 
Código #2: Usa caracteres anchos en el formulariowchar_t *, int

void print_wchars(wchar_t *s, int len)
{
    int n = 0;
    while (n < len)
    {
        printf("%x ", s[n]);
        n++;
    }
    printf("\n");
}

Las strings de Python deben convertirse a una codificación de bytes adecuada, como UTF-8, para la función orientada a bytes print_chars(). El código que figura a continuación es una función de extensión simple que resuelve el propósito.

Código #3:

static PyObject *py_print_chars(PyObject *self, PyObject *args)
{
    char *s;
    Py_ssize_t len;
    if (!PyArg_ParseTuple(args, "s#", &s, &len))
    {
        return NULL;
    }
    print_chars(s, len);
    Py_RETURN_NONE;
}

Para las funciones de biblioteca que funcionan con el wchar_t tipo nativo de la máquina, el código de extensión C se puede escribir como:

Código #4:

static PyObject * py_print_wchars(PyObject * self, PyObject * args)
{
    wchar_t * s;
    Py_ssize_t len;
    if (! PyArg_ParseTuple(args, "u#", &s, &len))
    {
        return NULL;
    }
    print_wchars(s, len);
    Py_RETURN_NONE;
}

Ahora el siguiente código comprueba cómo funcionan las funciones de extensión.

Debe observarse la forma en que la función orientada a bytes print_chars()recibe datos codificados en UTF-8, mientras print_wchars()que recibe los valores de punto de código Unicode.

Código #5:

s = 'Spicy Jalape\u00f1o'
print (print_chars(s))
  
print ("\n", print_wchars(s))

Producción :

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

53 70 69 63 79 20 4a 61 6c 61 70 65 f1 6f

Verifiquemos la naturaleza de la biblioteca C a la que se ha accedido. Para muchas bibliotecas de C, podría tener más sentido pasar bytes en lugar de una string. Usemos el código de conversión que se proporciona a continuación para hacerlo.

Código #6:

static PyObject *py_print_chars(PyObject *self, PyObject *args)
{
    char *s;
    Py_ssize_t len;
      
    // accepts bytes, bytearray, or other byte-like object 
      
    if (!PyArg_ParseTuple(args, "y#", &s, &len))
    {
        return NULL;
    }
    print_chars(s, len);
    Py_RETURN_NONE;
}

Si aún desea pasar strings, debe tener cuidado de que Python3 use una representación de string adaptable que no sea del todo sencilla de asignar directamente a las bibliotecas C usando los tipos estándar char * o wchar_t *. Por lo tanto, para presentar datos de string a C, casi siempre es necesario algún tipo de conversión. Los códigos de formato s# y u#PyArg_ParseTuple() para realizar dichas conversiones de manera segura.
Cada vez que se realiza una conversión, se adjunta una copia de los datos convertidos al objeto de string original para que pueda reutilizarse más tarde, como se muestra en el código a continuación.

Código #7:

import sys
  
s = 'Spicy Jalape\u00f1o'
print ("Size : ", sys.getsizeof(s))
  
print("\n", print_chars(s))
  
print ("\nSize : ", sys.getsizeof(s))
  
print ("\n", print_wchars(s))
  
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    

53 70 69 63 79 20 4a 61 6c 61 70 65 f1 6f

Size : 163    

Publicación traducida automáticamente

Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *