はじめに
こんにちは、ザワッチです!
音声認識モデルをエッジ推論しようとあれこれ試していたところ、かなりタフなエラーに遭遇しました。自分への備忘も兼ねて、原因と解決策をまとめます。
背景
Windows デスクトップアプリを Tauri で作り、そのバックエンドに Rust を使用しています。
この中で、Rust の ONNX Runtime バインディングである ort を Windows 環境で使おうとしたところ、onnxruntime.dll のバージョン不一致が原因でクラッシュしました。
実行環境
以下に関係ありそうな実行環境の情報を記載します。
OS
Windows 11 Pro x64 Version 10.0.26100
CPU
13th Gen Intel(R) Core(TM) i7-1355U
Rust / Tool Chain
rustc 1.89.0 (29483883e 2025-08-04)
cargo 1.89.0 (c24e10642 2025-06-23)
rustup stable-x86_64-pc-windows-msvc (default)
主要クレートと設定
ort = "=2.0.0-rc.10" features = ["ndarray", "load-dynamic", "download-binaries", "copy-dylibs"]
ONNX Runtime
1.22.1(CPU 版 / DirectML 版 いずれか)
※ ort 2.0.0-rc.10 は ONNX Runtime 1.22.x を要求します。
エラー内容
DLL バージョン不一致
thread 'main' panicked at ... ort-2.0.0-rc.10\src\lib.rs:168:39:
ort 2.0.0-rc.10 is not compatible with the ONNX Runtime binary found at `onnxruntime.dll`;
expected GetVersionString to return '1.22.x', but got '1.17.1'
→ Windows では DLL の探索順(exeと同じフォルダ、System32 など)が効くため、システムにある古い DLL を誤って拾うとクラッシュします。
で、なぜかcargo buildでortクレートをダウンロードしていたにもかかわらず、target/debug配下に.dllファイルが存在せず。
解決法
公式のGithubレポジトリからWindows向けバイナリ(1.22.1)をダウンロードしました。
ダウンロード、zip展開したのち、.../onnxruntime-win-x64-1.22.1\onnxruntime-win-x64-1.22.1\libにあるファイル群をどこかプロジェクトディレクトリにコピペして、tauri.conf.json にリソースを登録します。
{
"tauri": {
"bundle": {
"resources": ["resources/onnxruntime/**"]
}
}
}
そして、起動時(ort::init() より前)に ORT_DYLIB_PATH / PATH を設定します。
fn pin_ort_from_resources(app: &tauri::AppHandle) {
// 1) リソースから ORT の配置ディレクトリを解決
let dir0 = app.path()
.resolve("onnxruntime/win-x64", BaseDirectory::Resource)
.expect("resolve ORT dir");
// 2) Windows の拡張パス(\\?\)を通常パスに丸めておくと安全
#[cfg(target_os = "windows")]
let dir = dunce::simplified(&dir0).to_path_buf();
#[cfg(not(target_os = "windows"))]
let dir = dir0;
// 3) DLL を固定(load-dynamic 機能がこれを参照)
let dll = dir.join("onnxruntime.dll");
std::env::set_var("ORT_DYLIB_PATH", &dll);
// 4) プロバイダ DLL を見つけられるよう PATH の先頭に追加
let mut new_path = std::ffi::OsString::new();
new_path.push(&dir);
new_path.push(";");
if let Some(old) = std::env::var_os("PATH") { new_path.push(old); }
std::env::set_var("PATH", new_path);
}
// Tauri の起動時に呼ぶ(これより前で ORT を触らない)
fn main() {
tauri::Builder::default()
.setup(|app| {
pin_ort_from_resources(app.app_handle()); // 先にパスを通す
ort::init().commit().expect("init ort"); // その後に ORT 初期化
Ok(())
})
// … 省略 …
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
必要に応じて cargo clean ののち cargo build / npm run tauri devを実行
おわりに
Windows でのネイティブ連携は、DLL の探索順が落とし穴になりがちです。
今回のポイントは (1) 正しい DLL を確実に読ませる、(2) 参照パスをリソース基準に固定し、起動時に明示的に通す の2点でした。
Windows周りの開発はすんなりいかないことも多いですが、どなたかのハマり時間短縮になれば幸いです。