[Python] Issue regarding overlap of memory allocation for separate dataclasses

Discussão em 'Python' iniciado por Stack, Março 4, 2025.

  1. Stack

    Stack Membro Participativo

    I am experimenting with defining dataclasses for containing ctypes objects. I have defined three classes; two of which are used as attributes to the third:

    @dataclasses.dataclass
    class Point:
    x = ctypes.c_int(0)
    y = ctypes.c_int(0)

    @dataclasses.dataclass
    class Point2:
    x = ctypes.c_int(0)
    y = ctypes.c_int(0)

    @dataclasses.dataclass
    class TestObj:
    point1 = Point()
    point2 = Point()


    The TestObj class is then passed to a C function inc:

    #include <stdio.h>

    void inc(int *x, int *y)
    {
    *x = *x + 1;
    *y = *y + 1;
    }


    via a wrapper:

    def inc(test: TestObj):
    _inc = lib.inc

    _inc.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)]
    _inc.restype = None
    _inc(test.point1.x,test.point1.y)


    When investigating the result of the pass to inc I observe the snippet:

    test = TestObj()
    print(f"addressof test.point1.x = {ctypes.addressof(test.point1.x)}")
    print(f"test.point1.x.value = {test.point1.x.value}")
    print(f"addressof test.point1.y = {ctypes.addressof(test.point1.y)}")
    print(f"test.point1.y.value = {test.point1.y.value}")
    print(f"addressof test.point2.x = {ctypes.addressof(test.point2.x)}")
    print(f"test.point2.x.value = {test.point2.x.value}")
    print(f"addressof test.point2.y = {ctypes.addressof(test.point2.y)}")
    print(f"test.point2.y.value = {test.point2.y.value}")
    inc(test)
    print("after pass to inc")
    print(f"addressof test.point1.x = {ctypes.addressof(test.point1.x)}")
    print(f"test.point1.x.value = {test.point1.x.value}")
    print(f"addressof test.point1.y = {ctypes.addressof(test.point1.y)}")
    print(f"test.point1.y.value = {test.point1.y.value}")
    print(f"addressof test.point2.x = {ctypes.addressof(test.point2.x)}")
    print(f"test.point2.x.value = {test.point2.x.value}")
    print(f"addressof test.point2.y = {ctypes.addressof(test.point2.y)}")
    print(f"test.point2.y.value = {test.point2.y.value}")


    results in:

    addressof test.point1.x = 124872721403536
    test.point1.x.value = 0
    addressof test.point1.y = 124872719995280
    test.point1.y.value = 0
    addressof test.point2.x = 124872721403536
    test.point2.x.value = 0
    addressof test.point2.y = 124872719995280
    test.point2.y.value = 0
    after pass to inc
    addressof test.point1.x = 124872721403536
    test.point1.x.value = 1
    addressof test.point1.y = 124872719995280
    test.point1.y.value = 1
    addressof test.point2.x = 124872721403536
    test.point2.x.value = 1
    addressof test.point2.y = 124872719995280
    test.point2.y.value = 1


    the memory locations of the subsequent x and y attributes of each Point instance share the same memory location respectively and that the x and y attributes of each Point instance attributes of the TestObj instance are incremented, instead of just the point1 attributes.

    If I redefine TestObj as:

    @dataclasses.dataclass
    class TestObj:
    point1 = Point()
    point2 = Point2()


    and again pass it to the inc wrapper I observe the intended result of:

    addressof test.point1.x = 133142487043728
    test.point1.x.value = 0
    addressof test.point1.y = 133142485635472
    test.point1.y.value = 0
    addressof test.point2.x = 133142485635728
    test.point2.x.value = 0
    addressof test.point2.y = 133142485635984
    test.point2.y.value = 0
    after pass to inc
    addressof test.point1.x = 133142487043728
    test.point1.x.value = 1
    addressof test.point1.y = 133142485635472
    test.point1.y.value = 1
    addressof test.point2.x = 133142485635728
    test.point2.x.value = 0
    addressof test.point2.y = 133142485635984
    test.point2.y.value = 0


    While the x and y attributes of point1 and point2 share the same memory locations repspectively, now only the point1 x and y are incremented as intended.

    I am puzzled as to how this is happening, given that in both scenarios the x and y attributes seemingly share the same memory location, but the change in name of the Point attribute provides the intended result. I appreciate any and all help in understanding what is happening.

    Continue reading...

Compartilhe esta Página