You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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和Sync trait(通常数据库连接池、静态字符串字段均满足该要求,若未自动实现,需确认依赖库的线程安全特性)。

内容的提问来源于stack exchange,提问作者Håkan Troberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:37:50