import ctypes import json from pathlib import Path import time class MysqlDLLClient: """ MySQL DLL 调用客户端 用于调用 mysql_dll2.dll 执行 SQL Example ------- db = MysqlDLLClient() data = db.query( 7, "select * from min15_a_jq where times>=? and times<=?", ["2025-12-24 00:00:00", "2025-12-26 00:00:00"] ) print(data) """ def __init__(self, dll_path=None): """ 初始化 DLL Parameters ---------- dll_path : str | Path dll路径,默认当前目录 mysql_dll2.dll """ if dll_path is None: root = Path(__file__).resolve().parent.parent dll_path = root / "lib/mysql_dll/mysql_dll2.dll" self.dll = ctypes.WinDLL(str(dll_path)) self._init_functions() time.sleep(1) ret = self.dll.InitDBConfig() if ret != 1: raise RuntimeError("服务器授权失败") # --------------------------------------------------------- # 初始化 DLL 函数声明 # --------------------------------------------------------- def _init_functions(self): # 初始化数据库配置 self.dll.InitDBConfig.argtypes = [] self.dll.InitDBConfig.restype = ctypes.c_int # 关闭 DLL self.dll.ShutdownDLL.argtypes = [] self.dll.ShutdownDLL.restype = None # QuerySQL_Auto self.dll.QuerySQL_Auto.argtypes = [ ctypes.c_int, # db_index ctypes.c_char_p, # sql ctypes.c_char_p, # params ctypes.POINTER(ctypes.c_void_p), # out_buf ctypes.POINTER(ctypes.c_int) # out_size ] self.dll.QuerySQL_Auto.restype = ctypes.c_int # FreeBuffer self.dll.FreeBuffer.argtypes = [ctypes.c_void_p] self.dll.FreeBuffer.restype = None # --------------------------------------------------------- # 参数转换 # --------------------------------------------------------- def _build_params(self, params): """ 参数列表转 DLL 参数格式 ["2025-01-01","2025-01-02"] -> b"s:2025-01-01|s:2025-01-02" """ if not params: return b"" arr = [] for p in params: if isinstance(p, str): arr.append(f"s:{p}") elif isinstance(p, int): arr.append(f"i:{p}") elif isinstance(p, float): arr.append(f"f:{p}") else: raise TypeError(f"不支持的参数类型: {type(p)}") return "|".join(arr).encode() # --------------------------------------------------------- # 查询 # --------------------------------------------------------- def query(self, db_index, sql, params=None): """ 执行 SQL 查询 Parameters ---------- db_index : int 数据库编号 sql : str SQL语句 params : list SQL参数 Returns ------- str 查询结果(JSON 或文本) """ if isinstance(sql, str): sql = sql.encode() params_bytes = self._build_params(params) out_buf = ctypes.c_void_p() out_size = ctypes.c_int() ret = self.dll.QuerySQL_Auto( db_index, sql, params_bytes, ctypes.byref(out_buf), ctypes.byref(out_size) ) if ret != 0: raise RuntimeError("SQL执行失败") try: data = ctypes.string_at(out_buf.value, out_size.value) return json.loads(data.decode()) finally: self.dll.FreeBuffer(out_buf) # --------------------------------------------------------- # 关闭 # --------------------------------------------------------- def close(self): """关闭 DLL""" if self.dll: self.dll.ShutdownDLL() # --------------------------------------------------------- # with 支持 # --------------------------------------------------------- def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close()