Rust编写的DLL函数间共享数据库引用的实现方案
解决方案:通过全局带锁的可选值共享数据库连接实例
针对你的问题,核心思路是用**lazy_static + Mutex<Option<DBConn<MySql>>>**实现延迟初始化的线程安全全局数据库实例,同时复用Tokio Runtime处理异步操作。
1. 定义全局线程安全变量
首先确保Cargo.toml包含lazy_static和tokio依赖,然后定义全局的数据库实例容器与Runtime:
use lazy_static::lazy_static; use std::sync::Mutex; use tokio::runtime::Runtime; lazy_static! { // Option解决DBConn无默认构造函数的问题,Mutex保证多线程安全访问 static ref DB_INSTANCE: Mutex<Option<DBConn<MySql>>> = Mutex::new(None); // 全局复用Tokio Runtime,避免重复初始化开销 static ref GLOBAL_RUNTIME: Runtime = Runtime::new().unwrap(); }
2. 修改Init函数:初始化并存储全局实例
完成数据库连接后,将实例存入全局容器:
#[no_mangle] pub unsafe extern "C" fn Init() { const DB_CREDENTIALS: DatabaseCredentials<'static> = DatabaseCredentials { username: "root", password: "password", host: "localhost", port: "3306" }; // 复用全局Runtime执行异步操作 let dbms = GLOBAL_RUNTIME.block_on(async { DBMS::connect_with_credentials(DB_CREDENTIALS).await.unwrap() }); GLOBAL_RUNTIME.block_on(async { dbms.ensure_database("test_db").await.unwrap() }); let db = GLOBAL_RUNTIME.block_on(async { dbms.connect_database("test_db").await.unwrap() }); // 将初始化好的实例存入全局容器 let mut db_lock = DB_INSTANCE.lock().unwrap(); *db_lock = Some(db); }
3. 修改SaveValues函数:获取全局实例并执行操作
在函数内获取全局实例,处理未初始化的情况,并返回状态码给TypeScript:
#[no_mangle] pub unsafe extern "C" fn SaveValues(container_struct: &container) -> i32 { // 获取全局数据库实例的锁 let mut db_lock = match DB_INSTANCE.lock() { Ok(lock) => lock, Err(_) => return -3, // 锁中毒返回错误码 }; // 检查实例是否已初始化 let db = match db_lock.as_mut() { Some(instance) => instance, None => return -1, // 未调用Init返回错误码 }; // 用全局Runtime执行异步插入操作 match GLOBAL_RUNTIME.block_on(async { db.insert_table(container_struct).await }) { Ok(_) => 0, // 操作成功 Err(_) => -2 // 插入失败 } }
关键说明
Mutex<Option<T>>的作用:Option解决了DBConn无默认构造函数的问题,初始状态为None;Mutex保证多线程下的安全访问(Node.js的FFI调用可能在多线程执行,必须保证全局资源的线程安全)。- 全局Runtime:复用同一个Tokio Runtime,避免重复创建Runtime的开销,同时确保所有异步数据库操作在统一上下文执行。
- 错误码设计:通过不同整数错误码,让TypeScript层能清晰判断操作状态(未初始化、锁失败、插入失败等)。
- 线程安全校验:确保
DBConn<MySql>实现Send和Synctrait(通常数据库连接池、静态字符串字段均满足该要求,若未自动实现,需确认依赖库的线程安全特性)。
内容的提问来源于stack exchange,提问作者Håkan Troberg
相关产品推荐
相关产品推荐

