[Python-Dev] ctypes, memory mapped files and context manager
Nick Coghlan
ncoghlan at gmail.com
Wed Jan 4 21:37:20 EST 2017
On 5 January 2017 at 10:28, Hans-Peter Jansen <hpj at urpla.net> wrote:
> In order to get this working properly, the ctypes mapping needs a method to
> free the mapping actively. E.g.:
>
> @contextmanager
> def map_struct(m, n):
> m.resize(n * mmap.PAGESIZE)
> yield T.from_buffer(m)
> T.unmap_buffer(m)
>
> Other attempts with weakref and the like do not work due to the nature of the
> ctypes types.
I don't know ctypes well enough myself to comment on the idea of
offering fully deterministic cleanup, but the closest you could get to
that without requiring a change to ctypes is to have the context
manager introduce a layer of indirection:
class _T_data(ctypes.Structure):
_fields = [("foo", ctypes.c_uint32)]
class T:
def __init__(self, buffer):
self.data = _T_data.from_buffer(buffer)
def close(self):
self.data = None
@contextmanager
def map_struct(m, n):
m.resize(n * mmap.PAGESIZE)
mapped = T(m)
try:
yield mapped
finally:
mapped.close()
Client code would then need to consistently access the struct through
the data attribute:
with map_struct(m, 1) as a:
a.data.foo = 1
with map_struct(m, 2) as b:
b.data.foo = 2
Something like http://wrapt.readthedocs.io/en/latest/wrappers.html#object-proxy
would let you make the indirection to a contained object transparent,
but as far as I can tell, wrapt doesn't currently support "closing" a
proxy by replacing the reference to the internal object with a
reference to None (adding that might be possible, but I don't
personally know wrapt well enough to guess the feasibility of doing
so).
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev
mailing list