is_emulator=False):
if sys.platform == "android":
try:
- from ctypes import CDLL, c_char_p, create_string_buffer
+ from ctypes import CDLL, c_int, c_char_p, create_string_buffer
+ from ctypes.util import wrap_dll_function
except ImportError:
pass
else:
# An NDK developer confirmed that this is an officially-supported
# API (https://stackoverflow.com/a/28416743). Use `getattr` to avoid
# private name mangling.
- system_property_get = getattr(CDLL("libc.so"), "__system_property_get")
- system_property_get.argtypes = (c_char_p, c_char_p)
+ libc = CDLL("libc.so")
+
+ @wrap_dll_function(libc)
+ def __system_property_get(name: c_char_p, value: c_char_p) -> c_int:
+ pass
def getprop(name, default):
# https://android.googlesource.com/platform/bionic/+/refs/tags/android-5.0.0_r1/libc/include/sys/system_properties.h#39
PROP_VALUE_MAX = 92
buffer = create_string_buffer(PROP_VALUE_MAX)
- length = system_property_get(name.encode("UTF-8"), buffer)
+ length = __system_property_get(name.encode("UTF-8"), buffer)
if length == 0:
# This API doesn’t distinguish between an empty property and
# a missing one.
# windows.RtlAreLongPathsEnabled: RtlAreLongPathsEnabled()
# windows.is_admin: IsUserAnAdmin()
try:
- import ctypes
+ import ctypes.util
if not hasattr(ctypes, 'WinDLL'):
raise ImportError
except ImportError:
ntdll = ctypes.WinDLL('ntdll')
BOOLEAN = ctypes.c_ubyte
try:
- RtlAreLongPathsEnabled = ntdll.RtlAreLongPathsEnabled
+ @ctypes.util.wrap_dll_function(ntdll)
+ def RtlAreLongPathsEnabled() -> BOOLEAN:
+ pass
except AttributeError:
res = '<function not available>'
else:
- RtlAreLongPathsEnabled.restype = BOOLEAN
- RtlAreLongPathsEnabled.argtypes = ()
res = bool(RtlAreLongPathsEnabled())
info_add('windows.RtlAreLongPathsEnabled', res)
- shell32 = ctypes.windll.shell32
- IsUserAnAdmin = shell32.IsUserAnAdmin
- IsUserAnAdmin.restype = BOOLEAN
- IsUserAnAdmin.argtypes = ()
- info_add('windows.is_admin', IsUserAnAdmin())
+ @ctypes.util.wrap_dll_function(ctypes.windll.shell32)
+ def IsUserAnAdmin() -> BOOLEAN:
+ pass
+ info_add('windows.is_admin', bool(IsUserAnAdmin()))
try:
import _winapi
try:
from ctypes import CDLL, c_char_p, c_int
- android_log_write = getattr(CDLL("liblog.so"), "__android_log_write")
- android_log_write.argtypes = (c_int, c_char_p, c_char_p)
- ANDROID_LOG_INFO = 4
+ from ctypes.util import wrap_dll_function
+ liblog = CDLL("liblog.so")
+
+ @wrap_dll_function(liblog)
+ def __android_log_write(prio: c_int, tag: c_char_p,
+ text: c_char_p) -> c_int:
+ pass
# Separate tests using a marker line with a different tag.
+ ANDROID_LOG_INFO = 4
tag, message = "python.test", f"{self.id()} {time()}"
- android_log_write(
+ __android_log_write(
ANDROID_LOG_INFO, tag.encode("UTF-8"), message.encode("UTF-8"))
self.assert_log("I", tag, message, skip=True)
except:
# The global path configuration (_Py_path_config) must be a copy
# of the path configuration of PyInterpreter.config (PyConfig).
ctypes = import_helper.import_module('ctypes')
+ import ctypes.util # noqa: F811
- def get_func(name):
- func = getattr(ctypes.pythonapi, name)
- func.argtypes = ()
- func.restype = ctypes.c_wchar_p
- return func
-
- Py_GetPath = get_func('Py_GetPath')
- Py_GetPrefix = get_func('Py_GetPrefix')
- Py_GetExecPrefix = get_func('Py_GetExecPrefix')
- Py_GetProgramName = get_func('Py_GetProgramName')
- Py_GetProgramFullPath = get_func('Py_GetProgramFullPath')
- Py_GetPythonHome = get_func('Py_GetPythonHome')
+ @ctypes.util.wrap_dll_function(ctypes.pythonapi)
+ def Py_GetPath() -> ctypes.c_wchar_p:
+ pass
+
+ @ctypes.util.wrap_dll_function(ctypes.pythonapi)
+ def Py_GetPrefix() -> ctypes.c_wchar_p:
+ pass
+
+ @ctypes.util.wrap_dll_function(ctypes.pythonapi)
+ def Py_GetExecPrefix() -> ctypes.c_wchar_p:
+ pass
+
+ @ctypes.util.wrap_dll_function(ctypes.pythonapi)
+ def Py_GetProgramName() -> ctypes.c_wchar_p:
+ pass
+
+ @ctypes.util.wrap_dll_function(ctypes.pythonapi)
+ def Py_GetProgramFullPath() -> ctypes.c_wchar_p:
+ pass
+
+ @ctypes.util.wrap_dll_function(ctypes.pythonapi)
+ def Py_GetPythonHome() -> ctypes.c_wchar_p:
+ pass
config = _testinternalcapi.get_configs()['config']
HAVE_GETFINALPATHNAME = True
try:
- import ctypes
+ import ctypes.util
+ import ctypes.wintypes
except ImportError:
HAVE_GETSHORTPATHNAME = False
else:
HAVE_GETSHORTPATHNAME = True
def _getshortpathname(path):
- GSPN = ctypes.WinDLL("kernel32", use_last_error=True).GetShortPathNameW
- GSPN.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32]
- GSPN.restype = ctypes.c_uint32
+ kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
+
+ @ctypes.util.wrap_dll_function(kernel32)
+ def GetShortPathNameW(
+ lpszLongPath: ctypes.c_wchar_p,
+ lpszShortPath: ctypes.c_wchar_p,
+ cchBuffer: ctypes.wintypes.DWORD,
+ ) -> ctypes.wintypes.DWORD:
+ pass
+ GSPN = GetShortPathNameW
+
result_len = GSPN(path, None, 0)
if not result_len:
raise OSError("failed to get short path name 0x{:08X}"
.format(ctypes.get_last_error()))
+
result = ctypes.create_unicode_buffer(result_len)
result_len = GSPN(path, result, result_len)
return result[:result_len]
# subprocess to the parent that the interpreter is ready. When it
# becomes ready, send *sig* via os.kill to the subprocess and check
# that the return code is equal to *sig*.
- import ctypes
+ import ctypes.util
from ctypes import wintypes
import msvcrt
# process has exited, use PeekNamedPipe to see what's inside stdout
# without waiting. This is done so we can tell that the interpreter
# is started and running at a point where it could handle a signal.
- PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
- PeekNamedPipe.restype = wintypes.BOOL
- PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle
- ctypes.POINTER(ctypes.c_char), # stdout buf
- wintypes.DWORD, # Buffer size
- ctypes.POINTER(wintypes.DWORD), # bytes read
- ctypes.POINTER(wintypes.DWORD), # bytes avail
- ctypes.POINTER(wintypes.DWORD)) # bytes left
+ @ctypes.util.wrap_dll_function(ctypes.windll.kernel32)
+ def PeekNamedPipe(
+ hNamedPipe: wintypes.HANDLE,
+ lpBuffer: ctypes.POINTER(ctypes.c_char),
+ nBufferSize: wintypes.DWORD,
+ lpBytesRead: ctypes.POINTER(wintypes.DWORD),
+ lpTotalBytesAvail: ctypes.POINTER(wintypes.DWORD),
+ lpBytesLeftThisMessage: ctypes.POINTER(wintypes.DWORD),
+ ) -> wintypes.BOOL:
+ pass
+
msg = "running"
proc = subprocess.Popen([sys.executable, "-c",
"import sys;"
# Make a NULL value by creating a pointer with no argument.
NULL = ctypes.POINTER(ctypes.c_int)()
- SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
- SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int),
- wintypes.BOOL)
- SetConsoleCtrlHandler.restype = wintypes.BOOL
+
+ @ctypes.util.wrap_dll_function(ctypes.windll.kernel32)
+ def SetConsoleCtrlHandler(HandlerRoutine: ctypes.POINTER(ctypes.c_int),
+ Add: wintypes.BOOL) -> wintypes.BOOL:
+ pass
# Calling this with NULL and FALSE causes the calling process to
# handle Ctrl+C, rather than ignore it. This property is inherited
import ctypes.wintypes # noqa: F811
kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True)
- kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE
+ @ctypes.util.wrap_dll_function(kernel)
+ def GetCurrentProcess() -> ctypes.wintypes.HANDLE:
+ pass
- kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL
- kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE,
- ctypes.wintypes.LPDWORD)
+ @ctypes.util.wrap_dll_function(kernel)
+ def GetProcessHandleCount(khProcess: ctypes.wintypes.HANDLE,
+ pdwHandleCount: ctypes.wintypes.LPDWORD) -> ctypes.wintypes.BOOL:
+ pass
# This is a pseudo-handle that doesn't need to be closed
- hproc = kernel.GetCurrentProcess()
+ hproc = GetCurrentProcess()
handle_count = ctypes.wintypes.DWORD()
- ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
+ ok = GetProcessHandleCount(hproc, ctypes.byref(handle_count))
self.assertEqual(1, ok)
before_count = handle_count.value
import sys
# Function prototype for the handler function. Returns BOOL, takes a DWORD.
-HandlerRoutine = WINFUNCTYPE(wintypes.BOOL, wintypes.DWORD)
+HANDLER_ROUTINE = WINFUNCTYPE(wintypes.BOOL, wintypes.DWORD)
def _ctrl_handler(sig):
"""Handle a sig event and return 0 to terminate the process"""
print("UNKNOWN EVENT")
return 0
-ctrl_handler = HandlerRoutine(_ctrl_handler)
+ctrl_handler = HANDLER_ROUTINE(_ctrl_handler)
-SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
-SetConsoleCtrlHandler.argtypes = (HandlerRoutine, wintypes.BOOL)
-SetConsoleCtrlHandler.restype = wintypes.BOOL
+@ctypes.util.wrap_dll_function(ctypes.windll.kernel32)
+def SetConsoleCtrlHandler(HandlerRoutine: HANDLER_ROUTINE,
+ Add: wintypes.BOOL) -> wintypes.BOOL:
+ pass
if __name__ == "__main__":
# Add our console control handling function with value 1