172 lines
4.3 KiB
Python
172 lines
4.3 KiB
Python
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() |