Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy bytes from a ctypes Structure to a buffer created from create_string_buffer

Tags:

python

ctypes

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...

like image 273
Gabe Avatar asked Jul 31 '13 17:07

Gabe


People also ask

How does ctypes work?

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

How do I use Ctypes pointer?

Creating Pointers with ctypesPOINTER() takes as parameter the type of pointer you wish to create, an integer pointer for example. ctypes. pointer() takes as parameter an object, which it then returns a pointer to. The pointer() however, only accepts datatypes from the ctypes module.

What is CDLL in Python?

It is a big C++ codebase with a (very) thin python wrapper which uses CDLL to load the C++ and call some C functions that are available to allow primitive python scripting of the code.


1 Answers

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)
like image 147
Eryk Sun Avatar answered Sep 27 '22 21:09

Eryk Sun