This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients amaury.forgeotdarc, belopolsky, eryksun, meador.inge, memeplex
Date 2016-07-09.19:40:58
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1468093258.64.0.0904668746504.issue27274@psf.upfronthosting.co.za>
In-reply-to
Content
If your goal is to get a bytes object, I don't see the point of creating an array. string_at is simpler and more efficient. 

If you really must create an array, note that simple pointers (c_void_p, c_char_p, c_wchar_p) need special handling. They don't have a `contents` attribute, and their _type_ is a string. 

Also, I think combining from_address and addressof is a bit convoluted. I think it's cleaner to implement this using an array pointer:

    >>> ptr = POINTER(c_int)((c_int * 3)(1,2,3))
    >>> arr = POINTER(ptr._type_ * 3)(ptr.contents)[0]
    >>> arr[:]
    [1, 2, 3]

This also keeps the underlying ctypes object(s) properly referenced:

    >>> arr._b_base_
    <__main__.LP_c_int_Array_3 object at 0x7fb28471cd90>
    >>> arr._b_base_._objects['0']['1']
    <__main__.c_int_Array_3 object at 0x7fb28477da60>

whereas using from_address creates an array that dangerously doesn't own its own data and doesn't keep a reference to the owner:

    >>> arr2 = (ptr._type_ * 3).from_address(addressof(ptr.contents))
    >>> arr2._b_needsfree_
    0
    >>> arr2._b_base_ is None
    True
    >>> arr2._objects is None
    True

Let's create a larger array to ensure it's using an mmap region instead of the heap. This ensures a segfault when trying to access the memory block after it's deallocated:

    >>> ptr = POINTER(c_int)((c_int * 100000)(*range(100000)))
    >>> arr = (ptr._type_ * 100000).from_address(addressof(ptr.contents))
    >>> del ptr
    >>> x = arr[:]
    Segmentation fault (core dumped)

whereas using a dereferenced array pointer keeps the source data alive:

    >>> ptr = POINTER(c_int)((c_int * 100000)(*range(100000)))
    >>> arr = POINTER(ptr._type_ * 100000)(ptr.contents)[0]
    >>> del ptr
    >>> x = arr[:]
    >>> x[-5:]
    [99995, 99996, 99997, 99998, 99999]
History
Date User Action Args
2016-07-09 19:40:58eryksunsetrecipients: + eryksun, amaury.forgeotdarc, belopolsky, memeplex, meador.inge
2016-07-09 19:40:58eryksunsetmessageid: <1468093258.64.0.0904668746504.issue27274@psf.upfronthosting.co.za>
2016-07-09 19:40:58eryksunlinkissue27274 messages
2016-07-09 19:40:58eryksuncreate