python / python/cpython

ctypes._CData.from_buffer does not inherit _b_base_

Abierto
#135,894 1 comentario 1 reacción 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

docs topic-ctypes
Lenguaje dominante
Python
Estrellas
77.2k
Forks
35.9k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Continuing work from #135669, I have noticed another inconsistency.

from_buffer docs say:

This method returns a ctypes instance that shares the buffer of the source object.

_b_base_ docs say:

The _b_base_ read-only member is the root ctypes object that owns the memory block.

So, I assumed that, when passing a ctypes object as source to from_buffer, the _b_base_ from the resulting ctypes object would be inherited from source, however that is not the case.

To better visualize the issue, lets consider this code:

import ctypes

bindata = bytearray([
    0, 0, # [0].offset
    2, 0, # [0].variant
    8, 0, # [1].offset
    1, 0, # [1].variant

    # dynamic_part
    1, 2, 3, 4,
    5, 6,

    0, 0,

    9, 8, 7, 6,
])

class A(ctypes.Structure):
    _fields_ = [
        ("foo", ctypes.c_int),
    ]
class B(ctypes.Structure):
    _fields_ = [
        ("bar", ctypes.c_byte * 6),
    ]

class Message(ctypes.Structure):
    _fields_ = [
        ("offset", ctypes.c_uint16),
        ("variant", ctypes.c_uint16),
    ]

    variants = {
        1: A,
        2: B,
    }

    def get(self):
        root = self._b_base_._b_base_
        _type = self.variants[self.variant]

        try:
            return _type.from_buffer(root.dynamic_part, self.offset)
        except ValueError as e:
            e.add_note(f"Invalid data offset={self.offset} variant={self.variant}")
            raise

class FinalData(ctypes.Structure):
    _fields_ = [
        ("messages", Message * 2),
        ("dynamic_part", ctypes.c_ubyte * 12),
    ]

x = FinalData.from_buffer(bindata)

print(x)
print(x.dynamic_part._b_base_)

a = x.messages[1].get()
b = x.messages[0].get()
print(a)
print(a._b_base_)
print(b)
print(b._b_base_)

I expected the a._b_base_ and b._b_base_ would be <__main__.FinalData object at 0x7fbee293d3d0>, like x.dynamic_part._b_base_, instead it is None.

Linked PRs
  • gh-152706

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza revisando el PR enlazado gh-152706 y ejecutando el reproductor de ctypes proporcionado. Después inspecciona la implementación detrás de _CData.from_buffer y sus pruebas existentes; se considera terminado cuando la cadena de propiedad b_base del objeto resultante coincide con el comportamiento documentado de propiedad del buffer.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
backend
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bien especificado
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.