Byte arrays and DLLs

37 views
Skip to first unread message

Rob Cliffe

unread,
Jun 30, 2022, 5:44:57 PMJun 30
to
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

Eryk Sun

unread,
Jun 30, 2022, 6:46:13 PMJun 30
to
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

Edmondo Giovannozzi

unread,
Jul 1, 2022, 5:01:26 AMJul 1
to
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).


Rob Cliffe

unread,
Jul 3, 2022, 7:54:22 AMJul 3
to
That worked.  Many thanks Eryk.
Rob
Reply all
Reply to author
Forward
0 new messages