交叉编译Rust hidapi-rs到Android时libusb链接失败问题
解决Android加载Rust HID库时的
libusb_init符号缺失问题 问题本质
你碰到的dlopen failed: cannot locate symbol "libusb_init"错误,核心是Rust编译出的libMyLibrary.so默认是动态链接libusb,但Android系统里没自带这个库,就算手动提前加载libusb1.0.so,也没和你的库建立正确关联。
可行解决步骤
1. 给Rust库静态链接libusb(最推荐)
把libusb直接编译进你的Rust库,彻底消除动态依赖:
- 修改
Cargo.toml,给hidapi系列库开静态链接特性:# 用hidapi-rs的情况 hidapi = { version = "0.14", features = ["static-libusb"] } # 用hidapi-rusb的情况 hidapi-rusb = { version = "0.7", features = ["static"] } - 如果是自己手动编译的libusb,要在
build.rs里指定静态库路径:println!("cargo:rustc-link-search=/你的安卓libusb静态库路径/"); println!("cargo:rustc-link-lib=static=usb-1.0"); println!("cargo:rustc-link-lib=log"); // 安卓必需的日志依赖
2. 调整gradle和代码的库加载顺序
如果坚持动态链接,得确保libusb先被加载,且路径正确:
- 模块级
build.gradle里指定jniLibs目录:android { sourceSets { main { jniLibs.srcDirs += ['libs'] } } } - MainActivity里严格按顺序加载:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) System.loadLibrary("usb1.0") // 注意库名要去掉前缀lib和后缀.so System.loadLibrary("MyLibrary") // 后面的业务逻辑 }
3. 核对ABI架构完全匹配
别让libusb和Rust库的架构不一致(比如一个arm64-v8a一个armeabi-v7a):
- 模块级
build.gradle里明确指定ABI:android { defaultConfig { ndk { abiFilters 'arm64-v8a', 'armeabi-v7a' } } } - 编译libusb时,要对应指定目标架构,比如编译arm64就用:
./configure --host=aarch64-linux-android make
4. 检查Rust库的链接状态
用Android NDK的readelf工具确认你的库是否还依赖动态libusb:
# 替换成你的NDK路径和库路径 ~/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-readelf -d libMyLibrary.so | grep NEEDED
如果输出里还有libusb-1.0.so,说明静态链接没生效,回去检查Cargo.toml或build.rs的配置。
为啥MacOS没问题?
MacOS系统默认自带libusb,所以动态链接能正常找到依赖,但Android是独立的嵌入式系统,没有这个默认配置,必须自己处理依赖。
内容的提问来源于stack exchange,提问作者HParish
相关产品推荐
相关产品推荐

