8

I have a ctypes structure (for example):

from ctypes import *
class Foo(Structure):
   _fields_ = [('f1',c_uint),
               ('f2',c_uint)]

I would like to copy an instance of that structure in to a buffer that was created from create_string_buffer (that is larger in size than needed for a single instance of Foo).

Example:

f = Foo()
f.f1=1; f.f2=2;
buf = create_string_buffer(100)
buf[0:sizeof(f)] = f

I know you can read and write data to/from structures on file objects (i.e. open('bar','rb').readinto(f) ), so it seems that there should be some way to do this easily too...

1 Answer 1

11

Avoid using an operation that makes a temporary copy, or that creates temporary objects while iterating. This should be a direct copy from the source buffer to the target buffer. It's simplest to use ctypes.memmove:

f = Foo()
f.f1=1
f.f2=2

buf = (c_char * 100)()
memmove(buf, byref(f), sizeof(f))

Or use a temporary array created with from_buffer (not a copy):

memoryview(buf)[:sizeof(f)] = (c_char * sizeof(f)).from_buffer(f)

The latter doesn't work in Python 3, however. It should work, but the buffer format codes that ctypes uses aren't supported by memoryview.

If you wanted a new array that was the same size or smaller, you could use the array type's from_buffer_copy method (2.6+):

buf = (c_char * sizeof(f)).from_buffer_copy(f)
Sign up to request clarification or add additional context in comments.

3 Comments

What if I want to do it the other way around? A buffer into a ctype structure with a size and data.
@marsh, use memmove to copy data into an existing struct, but if you're creating a new instance, try the from_buffer_copy constructor instead.
You can use memoryview(buf).cast('B') to discard the unwanted format code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.