-
Notifications
You must be signed in to change notification settings - Fork 674
Expand file tree
/
Copy pathctypesutil.py
More file actions
94 lines (74 loc) · 2.41 KB
/
ctypesutil.py
File metadata and controls
94 lines (74 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# type: ignore
"""
This module contains common `ctypes` utils.
"""
import ctypes
import logging
import sys
from typing import Any, Callable, Optional, Tuple, Union
log = logging.getLogger("can.ctypesutil")
__all__ = ["CLibrary", "HANDLE", "PHANDLE", "HRESULT"]
try:
_LibBase = ctypes.WinDLL
_FUNCTION_TYPE = ctypes.WINFUNCTYPE
except AttributeError:
_LibBase = ctypes.CDLL
_FUNCTION_TYPE = ctypes.CFUNCTYPE
class CLibrary(_LibBase):
def __init__(self, library_or_path: Union[str, ctypes.CDLL]) -> None:
self.func_name: Any
if isinstance(library_or_path, str):
super().__init__(library_or_path)
else:
super().__init__(library_or_path._name, library_or_path._handle)
def map_symbol(
self,
func_name: str,
restype: Any = None,
argtypes: Tuple[Any, ...] = (),
errcheck: Optional[Callable[..., Any]] = None,
) -> Any:
"""
Map and return a symbol (function) from a C library. A reference to the
mapped symbol is also held in the instance
:param func_name:
symbol_name
:param ctypes.c_* restype:
function result type (i.e. ctypes.c_ulong...), defaults to void
:param tuple(ctypes.c_* ... ) argtypes:
argument types, defaults to no args
:param callable errcheck:
optional error checking function, see ctypes docs for _FuncPtr
"""
if argtypes:
prototype = _FUNCTION_TYPE(restype, *argtypes)
else:
prototype = _FUNCTION_TYPE(restype)
try:
func = prototype((func_name, self))
except AttributeError:
raise ImportError(
f'Could not map function "{func_name}" from library {self._name}'
) from None
func._name = func_name # pylint: disable=protected-access
log.debug(
'Wrapped function "%s", result type: %s, error_check %s',
func_name,
type(restype),
errcheck,
)
if errcheck is not None:
func.errcheck = errcheck
setattr(self, func_name, func)
return func
if sys.platform == "win32":
HRESULT = ctypes.HRESULT
elif sys.platform == "cygwin":
class HRESULT(ctypes.c_long):
pass
else:
HRESULT = None
# Common win32 definitions
class HANDLE(ctypes.c_void_p):
pass
PHANDLE = ctypes.POINTER(HANDLE)