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
| import ctypes from pathlib import Path
_CALLBACK = ctypes.CFUNCTYPE(None, ctypes.c_char_p, ctypes.c_void_p)
class Calculator: def __init__(self): lib_path = (Path(__file__).parent / "libdemo.so").resolve() self._lib = ctypes.CDLL(str(lib_path)) self._lib.demo_create.argtypes = [] self._lib.demo_create.restype = ctypes.c_void_p self._lib.demo_destroy.argtypes = [ctypes.c_void_p] self._lib.demo_destroy.restype = None self._lib.demo_add.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] self._lib.demo_add.restype = ctypes.c_int self._lib.demo_get_name.argtypes = [ctypes.c_void_p] self._lib.demo_get_name.restype = ctypes.c_void_p self._lib.demo_free_string.argtypes = [ctypes.c_void_p] self._lib.demo_free_string.restype = None self._lib.demo_set_callback.argtypes = [ ctypes.c_void_p, _CALLBACK, ctypes.c_void_p, ] self._lib.demo_set_callback.restype = None self._handle = self._lib.demo_create() self._callback = None
def add(self, a: int, b: int) -> int: if not self._handle: raise RuntimeError("Calculator 未初始化") return int(self._lib.demo_add(self._handle, a, b))
def get_name(self) -> str: if not self._handle: raise RuntimeError("Calculator 未初始化") ptr = self._lib.demo_get_name(self._handle) if not ptr: return "" raw = ctypes.cast(ptr, ctypes.c_char_p).value or b"" self._lib.demo_free_string(ptr) return raw.decode("utf-8", errors="ignore")
def set_callback(self, callback) -> None: if not self._handle: raise RuntimeError("Calculator 未初始化") if callback is None: raise RuntimeError("回调不能为空")
def _bridge(message_ptr, user_data): text = message_ptr.decode("utf-8", errors="ignore") if message_ptr else "" callback(text)
self._callback = _CALLBACK(_bridge) self._lib.demo_set_callback(self._handle, self._callback, None)
def close(self) -> None: if self._handle: self._lib.demo_destroy(self._handle) self._handle = None self._callback = None
|