ctypes._CData.from_buffer does not inherit _b_base_
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 77.2k
- Forks
- 35.9k
- PR merge metrics
- PR metrics pending
Description
Continuing work from #135669, I have noticed another inconsistency.
This method returns a ctypes instance that shares the buffer of the source object.
The _b_base_ read-only member is the root ctypes object that owns the memory block.
So, I assumed that, when passing a ctypes object as source to from_buffer, the _b_base_ from the resulting ctypes object would be inherited from source, however that is not the case.
To better visualize the issue, lets consider this code:
import ctypes
bindata = bytearray([
0, 0, # [0].offset
2, 0, # [0].variant
8, 0, # [1].offset
1, 0, # [1].variant
# dynamic_part
1, 2, 3, 4,
5, 6,
0, 0,
9, 8, 7, 6,
])
class A(ctypes.Structure):
_fields_ = [
("foo", ctypes.c_int),
]
class B(ctypes.Structure):
_fields_ = [
("bar", ctypes.c_byte * 6),
]
class Message(ctypes.Structure):
_fields_ = [
("offset", ctypes.c_uint16),
("variant", ctypes.c_uint16),
]
variants = {
1: A,
2: B,
}
def get(self):
root = self._b_base_._b_base_
_type = self.variants[self.variant]
try:
return _type.from_buffer(root.dynamic_part, self.offset)
except ValueError as e:
e.add_note(f"Invalid data offset={self.offset} variant={self.variant}")
raise
class FinalData(ctypes.Structure):
_fields_ = [
("messages", Message * 2),
("dynamic_part", ctypes.c_ubyte * 12),
]
x = FinalData.from_buffer(bindata)
print(x)
print(x.dynamic_part._b_base_)
a = x.messages[1].get()
b = x.messages[0].get()
print(a)
print(a._b_base_)
print(b)
print(b._b_base_)
I expected the a._b_base_ and b._b_base_ would be <__main__.FinalData object at 0x7fbee293d3d0>, like x.dynamic_part._b_base_, instead it is None.
Linked PRs
- gh-152706
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing linked PR gh-152706 and running the supplied ctypes reproducer. Then inspect the implementation behind _CData.from_buffer and its existing tests; done means the resulting object’s b_base ownership chain matches the documented buffer ownership behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100