• Byte arrays and DLLs

    From Rob Cliffe@21:1/5 to All on Thu Jun 30 22:36:09 2022
    I have an application in which I wanted a fixed-length "array of bytes"
    (that's intended as an informal term) where I could read and write
    individual bytes and slices, and also pass the array to a DLL (one I
    wrote in C) which expects an "unsigned char *" parameter.
    I am using ctypes to talk to the DLL but am open to alternatives. Speed
    is important.  My OS is Windows 10.
    I started off using a bytearray object (bytes does not support item assignment), but I couldn't find any way of passing it to the DLL
    directly.  Instead I had to convert it to a different type before
    passing it, e.g.
        bytes(MyArray)
    or
        (ctypes.c_char * LEN).from_buffer(MyArray)) # LEN is the length of MyArray, knownin advance
    but this was slow, I think because the array data is being copied to a
    separate object.
    Eventually after consulting Googol I came up with using a memoryview:

        MyArray = memoryview(bytearray(   <required-length> )) # can read
    and write to this

    and passing it to the DLL as

        MyArray.tobytes()

    and was gratified to see a modest speed improvement.  (I don't know for
    sure if it is still copying the array data, though I would guess not.)
    Is this a sensible approach, or am I still missing something?

    AKAIK it is not possible to give ctypes a bytearray object and persuade
    it to give you a pointer to the actual array data, suitable for passing
    to a DLL.  Is this (a) false (b) for historical reasons (c) for some
    other good reason?
    TIA
    Rob Cliffe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eryk Sun@21:1/5 to Rob Cliffe via Python-list on Thu Jun 30 17:45:49 2022
    On 6/30/22, Rob Cliffe via Python-list <python-list@python.org> wrote:

    AKAIK it is not possible to give ctypes a bytearray object and persuade
    it to give you a pointer to the actual array data, suitable for passing
    to a DLL.

    You're overlooking the from_buffer() method. For example:

    >>> ba = bytearray(10)
    >>> ca = (ctypes.c_char * len(ba)).from_buffer(ba)
    >>> ca.value = b'spam&eggs'
    >>> ba
    bytearray(b'spam&eggs\x00')

    Note that the bytearray can't be resized while a view of the data is
    exported. For example:

    >>> ba.append(97)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    BufferError: Existing exports of data: object cannot be re-sized

    >>> del ba[-1]
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    BufferError: Existing exports of data: object cannot be re-sized

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Edmondo Giovannozzi@21:1/5 to All on Fri Jul 1 02:01:04 2022
    Il giorno venerdì 1 luglio 2022 alle 00:46:13 UTC+2 ery...@gmail.com ha scritto:
    On 6/30/22, Rob Cliffe via Python-list <pytho...@python.org> wrote:

    AKAIK it is not possible to give ctypes a bytearray object and persuade
    it to give you a pointer to the actual array data, suitable for passing
    to a DLL.
    You're overlooking the from_buffer() method. For example:

    ba = bytearray(10)
    ca = (ctypes.c_char * len(ba)).from_buffer(ba)
    ca.value = b'spam&eggs'
    ba
    bytearray(b'spam&eggs\x00')

    Note that the bytearray can't be resized while a view of the data is exported. For example:

    ba.append(97)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    BufferError: Existing exports of data: object cannot be re-sized

    del ba[-1]
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    BufferError: Existing exports of data: object cannot be re-sized

    Have you had a look at numpy (https://numpy.org/)?
    Typically, it is used for all scientific applications, supports several different kind of array, fast linear algebra, etc.
    And of course you can pass an array to a dynamic library with ctypes (https://numpy.org/doc/stable/reference/routines.ctypeslib.html).



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rob Cliffe@21:1/5 to Eryk Sun on Sun Jul 3 10:32:09 2022
    That worked.  Many thanks Eryk.
    Rob

    On 30/06/2022 23:45, Eryk Sun wrote:
    On 6/30/22, Rob Cliffe via Python-list <python-list@python.org> wrote:
    AKAIK it is not possible to give ctypes a bytearray object and persuade
    it to give you a pointer to the actual array data, suitable for passing
    to a DLL.
    You're overlooking the from_buffer() method. For example:

    >>> ba = bytearray(10)
    >>> ca = (ctypes.c_char * len(ba)).from_buffer(ba)
    >>> ca.value = b'spam&eggs'
    >>> ba
    bytearray(b'spam&eggs\x00')

    Note that the bytearray can't be resized while a view of the data is exported. For example:

    >>> ba.append(97)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    BufferError: Existing exports of data: object cannot be re-sized

    >>> del ba[-1]
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    BufferError: Existing exports of data: object cannot be re-sized

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)