0

I need to write a function that returns an object by its id. I can't use ctypes.cast, _ctypes, gc, locals, globals, etc., it is recommended to use struct and ctypes. For example, for an object of type int, I write the following:

struct.unpack ("LLli", ctypes.string_at (id_of_object, 28))

if i know the size of the object is 28 bytes. But the object can be of any size. For example, for object = 2**30 the size will be 32 bytes. Can I somehow get the size of the object itself by its id? Or do I need to use some other methods in this task?

  • 1
    Have you already read the answers [here](https://stackoverflow.com/questions/1396668/get-object-by-id) and [here](https://stackoverflow.com/questions/15011674/is-it-possible-to-dereference-variable-ids)? – RufusVS Oct 04 '21 at 02:28
  • Why *can't* you use `ctypes.cast` but *can* use `ctypes.string_at`? That's a strange restriction. As the links in the previous comment point out, this isn't a good idea regardless. – Mark Tolonen Oct 04 '21 at 20:02
  • It's just learning tasks, I guess our mentors wanted us to understand how different objects lie in memory. – Piboldi Refliction Oct 06 '21 at 17:06
  • Fair enough. But I suggest to start with *CTypes* types (that you know the layout). Then and only then (when you have enough experience with *CPython* implementation details) move to generic objects. – CristiFati Oct 09 '21 at 07:07

1 Answers1

0

Any object starts with a reference count and a reference type. My problem can be solved like this: first, using ctypes.string_at, we get a reference to the type, it will be the second in the tuple:

struct.unpack ("LL", ctypes.string_at (object_id, 16))

Then, for example, in the case of the int type, we get the number of "pieces" of the object, it will be the third in the tuple:

info = struct.unpack ("LLl", ctypes.string_at (object_id, 24))

And finally, we get the whole number:

num_of_pieces = abs (info [2])
size_of_obj = 24 + 4 * num_of_pieces
type_string = "i" * num_of_pieces
number = struct.unpack ("LLl" + type_string, ctypes.string_at (object_id, size_of_obj))
i = 0
res = 0
for n in number [3:]:
    res + = n * (2 ** 30) ** i
    i + = 1
return res if info [2]> 0 else -res

With other types everything will be a bit different, I had to deal with each case separately.