1

Given a ctypes structure and instances:

class MyStruct(Structure):
    _fields_ = [
        ('length', c_int),
        ('data', c_void_p)
    ]

one = MyStruct()
two = MyStruct()

How can I make a copy of the content that one.data points to and make two.data point to the new memory copy. I don't just want to copy the pointers themselves.

Assuming one.data != two.data, it seems like the answer should be quite straight forward using memmove, such as:

memmove(two.data, one.data, one.length)

But I can't quite get it right.

101
  • 8,514
  • 6
  • 43
  • 69
  • possible duplicate of [How to copy all properties of an object to another object, in Python?](http://stackoverflow.com/questions/243836/how-to-copy-all-properties-of-an-object-to-another-object-in-python) – fuesika Apr 03 '15 at 05:07
  • 1
    @pyStarter don't think that's the same thing. `c_void_p` is just an integer, but I want to copy the memory space it points to. – 101 Apr 03 '15 at 05:11
  • 1
    Copy the buffer to a new array and then store a pointer and the length to `two`. Try this: `a_t = c_char * one.length;` `tmp = a_t.from_buffer_copy(a_t.from_address(one.data));` `two.length = one.length;` `two.data = cast(tmp, c_void_p)`. Note that this doesn't get the address to assign using `addressof`; casting the array to `c_void_p` and assigning this to `two.data` ensures that `two._objects` references the array copy, which keeps it alive. – Eryk Sun Apr 03 '15 at 05:32
  • Thanks @eryksun I'll try that. Can you comment on why `memmove` isn't the way to go, seems like that would be the simplest way to do it (if it worked)? – 101 Apr 03 '15 at 05:37
  • 1
    The `two` struct only has a pointer, which will initially be `NULL` (0). You have to actually allocate memory for the copy. Instead of using the `from_buffer_copy` constructor, you could allocate the array and copy like this instead, if you prefer: `tmp = (c_char * one.length)();` `memmove(tmp, one.data, one.length)`. Then assign the array's address and length: `two.length = one.length;` `two.data = cast(tmp, c_void_p)`. – Eryk Sun Apr 03 '15 at 05:49
  • 1
    It's probably a wash on efficiency vs readability either way. The first way has to create a temporary array using `from_address` (but note that this copies no memory). OTOH, `memmove` is implemented as an FFI call, which invokes a lot of machinery. – Eryk Sun Apr 03 '15 at 05:54

0 Answers0