Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 18b8b57

Browse files
committed
Fix windows
1 parent 39b0803 commit 18b8b57

File tree

3 files changed

+142
-8
lines changed

3 files changed

+142
-8
lines changed

shared_memory/_winshmem.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import _winapi
2+
import ctypes.wintypes
3+
from ctypes import c_ulong, byref, sizeof
4+
5+
SIZE_T = c_ulong
6+
7+
INVALID_HANDLE_VALUE = ctypes.wintypes.HANDLE(-1)
8+
9+
PAGE_READWRITE = 0x04
10+
11+
FILE_MAP_COPY = 1
12+
FILE_MAP_WRITE = 2
13+
FILE_MAP_READ = 4
14+
15+
16+
_CreateFileMapping = ctypes.windll.kernel32.CreateFileMappingW
17+
_CreateFileMapping.argtypes = [
18+
ctypes.wintypes.HANDLE,
19+
ctypes.wintypes.LPVOID,
20+
ctypes.wintypes.DWORD,
21+
ctypes.wintypes.DWORD,
22+
ctypes.wintypes.DWORD,
23+
ctypes.wintypes.LPWSTR,
24+
]
25+
_CreateFileMapping.restype = ctypes.wintypes.HANDLE
26+
27+
28+
def CreateFileMapping(hFile, lpFileMappingAttributes, flProtect,
29+
dwMaximumSizeHigh, dwMaximumSizeLow, lpName):
30+
handle = _CreateFileMapping(hFile, lpFileMappingAttributes, flProtect,
31+
dwMaximumSizeHigh, dwMaximumSizeLow, lpName)
32+
if handle is None:
33+
last_err = _winapi.GetLastError()
34+
raise OSError(last_err)
35+
return handle
36+
37+
38+
_OpenFileMapping = ctypes.windll.kernel32.OpenFileMappingW
39+
_OpenFileMapping.argtypes = [
40+
ctypes.wintypes.DWORD,
41+
ctypes.wintypes.BOOL,
42+
ctypes.wintypes.LPWSTR
43+
]
44+
_OpenFileMapping.restype = ctypes.wintypes.HANDLE
45+
46+
47+
def OpenFileMapping(dwDesiredAccess, hInheritedHandle, lpName):
48+
handle = _OpenFileMapping(dwDesiredAccess, hInheritedHandle, lpName)
49+
if handle is None:
50+
last_err = _winapi.GetLastError()
51+
if last_err == 2:
52+
raise FileNotFoundError
53+
else:
54+
raise OSError(last_err)
55+
return handle
56+
57+
58+
_MapViewOfFile = ctypes.windll.kernel32.MapViewOfFile
59+
_MapViewOfFile.argtypes = [
60+
ctypes.wintypes.HANDLE,
61+
ctypes.wintypes.DWORD,
62+
ctypes.wintypes.DWORD,
63+
ctypes.wintypes.DWORD,
64+
SIZE_T
65+
]
66+
_MapViewOfFile.restype = ctypes.wintypes.LPVOID
67+
68+
69+
def MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
70+
dwFileOffsetLow, dwNumberOfBytesToMap):
71+
ptr = _MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
72+
dwFileOffsetLow, dwNumberOfBytesToMap)
73+
if ptr is None:
74+
last_err = _winapi.GetLastError()
75+
raise OSError(last_err)
76+
return ptr
77+
78+
79+
class MEMORY_BASIC_INFORMATION32(ctypes.Structure):
80+
"""
81+
MEMORY_BASIC_INFORMATION contains information about a
82+
particular region of memory. A call to kernel32.VirtualQuery()
83+
populates this structure
84+
"""
85+
_fields_ = [
86+
("BaseAddress", ctypes.wintypes.LPVOID),
87+
("AllocationBase", ctypes.wintypes.LPVOID),
88+
("AllocationProtect", ctypes.wintypes.DWORD),
89+
("RegionSize", ctypes.wintypes.DWORD),
90+
("State", ctypes.wintypes.DWORD),
91+
("Protect", ctypes.wintypes.DWORD),
92+
("Type", ctypes.wintypes.DWORD),
93+
]
94+
95+
96+
class MEMORY_BASIC_INFORMATION64(ctypes.Structure):
97+
"""
98+
MEMORY_BASIC_INFORMATION contains information about a
99+
particular region of memory. A call to kernel32.VirtualQuery()
100+
populates this structure
101+
"""
102+
_fields_ = [
103+
("BaseAddress", ctypes.wintypes.LPVOID),
104+
("AllocationBase", ctypes.wintypes.LPVOID),
105+
("AllocationProtect", ctypes.wintypes.DWORD),
106+
("__alignment1", ctypes.wintypes.DWORD),
107+
("RegionSize", ctypes.wintypes.DWORD),
108+
("State", ctypes.wintypes.DWORD),
109+
("Protect", ctypes.wintypes.DWORD),
110+
("Type", ctypes.wintypes.DWORD),
111+
("__alignment2", ctypes.wintypes.DWORD),
112+
]
113+
114+
115+
MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION64 if sizeof(ctypes.c_void_p) == 8 \
116+
else MEMORY_BASIC_INFORMATION32
117+
118+
119+
VirtualQuery = ctypes.windll.kernel32.VirtualQuery
120+
VirtualQuery.argtypes = [
121+
ctypes.wintypes.LPCVOID,
122+
ctypes.POINTER(MEMORY_BASIC_INFORMATION),
123+
SIZE_T
124+
]
125+
VirtualQuery.restype = SIZE_T
126+
127+
128+
def VirtualQuerySize(address):
129+
mbi = MEMORY_BASIC_INFORMATION()
130+
ret_size = VirtualQuery(address, byref(mbi), sizeof(mbi))
131+
assert ret_size == sizeof(mbi)
132+
return mbi.RegionSize

shared_memory/shared_memory.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
if os.name == "nt":
1818
import _winapi
19+
from . import _winshmem
1920
_USE_POSIX = False
2021
else:
2122
from . import _posixshmem
@@ -124,10 +125,10 @@ def __init__(self, name=None, create=False, size=0):
124125
temp_name = _make_filename() if name is None else name
125126
# Create and reserve shared memory block with this name
126127
# until it can be attached to by mmap.
127-
h_map = _winapi.CreateFileMapping(
128-
_winapi.INVALID_HANDLE_VALUE,
128+
h_map = _winshmem.CreateFileMapping(
129+
_winshmem.INVALID_HANDLE_VALUE,
129130
_winapi.NULL,
130-
_winapi.PAGE_READWRITE,
131+
_winshmem.PAGE_READWRITE,
131132
(size >> 32) & 0xFFFFFFFF,
132133
size & 0xFFFFFFFF,
133134
temp_name
@@ -154,22 +155,22 @@ def __init__(self, name=None, create=False, size=0):
154155
self._name = name
155156
# Dynamically determine the existing named shared memory
156157
# block's size which is likely a multiple of mmap.PAGESIZE.
157-
h_map = _winapi.OpenFileMapping(
158-
_winapi.FILE_MAP_READ,
158+
h_map = _winshmem.OpenFileMapping(
159+
_winshmem.FILE_MAP_READ,
159160
False,
160161
name
161162
)
162163
try:
163-
p_buf = _winapi.MapViewOfFile(
164+
p_buf = _winshmem.MapViewOfFile(
164165
h_map,
165-
_winapi.FILE_MAP_READ,
166+
_winshmem.FILE_MAP_READ,
166167
0,
167168
0,
168169
0
169170
)
170171
finally:
171172
_winapi.CloseHandle(h_map)
172-
size = _winapi.VirtualQuerySize(p_buf)
173+
size = _winshmem.VirtualQuerySize(p_buf)
173174
self._mmap = mmap.mmap(-1, size, tagname=name)
174175

175176
self._size = size

shared_memory/tests/test_shared_memory.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import warnings
1212
from shared_memory.shared_memory import _USE_POSIX
1313

14+
1415
def strip_python_stderr(stderr):
1516
"""Strip the stderr of a Python process from potential debug output
1617
emitted by the interpreter.

0 commit comments

Comments
 (0)