import ctypes from ctypes import ( Structure, POINTER, c_void_p, c_char_p, c_uint8, c_uint16, c_uint32, c_uint64, c_int16, c_bool ) class EskinSdkVersion(Structure): _fields_ = [ ("major", c_uint16), ("minor", c_uint16), ("patch", c_uint16), ] class EskinDevice: def __init__(self, lib_path: str): self._lib = ctypes.CDLL(lib_path) self._setup_functions() self._handle = None def _setup_functions(self): lib = self._lib lib.eskin_version.restype = EskinSdkVersion lib.eskin_version.argtypes = [] lib.eskin_open.restype = c_void_p lib.eskin_open.argtypes = [c_char_p, c_void_p] lib.eskin_close.restype = c_uint32 lib.eskin_close.argtypes = [c_void_p] lib.eskin_read_register.restype = c_uint32 lib.eskin_read_register.argtypes = [ c_void_p, c_uint32, c_uint16, POINTER(c_uint8), c_uint32, POINTER(c_uint32) ] lib.eskin_write_register.restype = c_uint32 lib.eskin_write_register.argtypes = [ c_void_p, c_uint32, POINTER(c_uint8), c_uint16, POINTER(c_uint16) ] def version(self) -> tuple: v = self._lib.eskin_version() return (v.major, v.minor, v.patch) def open(self, path: str): handle = self._lib.eskin_open(path.encode("utf-8"), None) if not handle: raise RuntimeError(f"Failed to open device: {path}") self._handle = handle def close(self): if self._handle: self._lib.eskin_close(self._handle) self._handle = None def read_register(self, addr: int, length: int) -> bytes: """读寄存器,返回原始字节""" buf = (c_uint8 * 256)() actual = c_uint32(0) err = self._lib.eskin_read_register( self._handle, addr, length, buf, len(buf), ctypes.byref(actual) ) if err != 0: raise RuntimeError(f"read_register failed: error={err}") return bytes(buf[:actual.value]) def write_register(self, addr: int, data: bytes) -> int: """写寄存器,返回设备确认的字节数""" arr = (c_uint8 * len(data))(*data) ret = c_uint16(0) err = self._lib.eskin_write_register( self._handle, addr, arr, len(data), ctypes.byref(ret) ) if err != 0: raise RuntimeError(f"write_register failed: error={err}") return ret.value def __enter__(self): return self def __exit__(self, *args): self.close()