FFI链接C ABI动态链接库(实操分享)crate就可达成·运行时·链接的功能要求。至于使用第三方crate所带来的好处,我将在文章末尾给出解释与列举。rs代码里,使用extern { ... }块导入外部函数。代码模板如下:#[link(name = "actual_lib_name_without_extname")] extern {
#[link_name = "actual_external_function_name"] // 支持对`FFI`函数重命名
fn external_function_local_alias(_: *const c_char) -> *const c_char; // 原始指针`*const c_char`是对`FFI`安全的。
...
}
上述【代码模板】解释:
actual_lib_name_without_extname需要被替换为【链接库文件名(不含扩展名与lib前缀)】actual_external_function_name需要被替换为【外部函数真实名字】external_function_local_alias需要被替换为【外部函数的本地别名】。即,根据本地命名规范,对外部函数·重命名。
$RUSTFLAGSexport RUSTFLAGS=-L native=<链接库搜索目录>
C ABI动态链接库(文件)】必须被预置于此<链接库搜索目录>下。= note: ld.exe: cannot find -l<链接库文件名>。$RUSTFLAGS会将【编译器配置指令-L】传递给rustc核心和向Library Search Path清单临时添加一个新检索目录。Cargo Package根目录为起点的【相对路径】。native=前缀表示:在该<链接库搜索目录>下预存都是C ABI链接库,而不是Rust ABI链接库。.cargo\config.toml [build] rustflags = "***"配置项内,设置此-L编译器参数不管用 — 原因不详且和Cargo Book文档描述不符。cargo build编译出一个.exe可执行文件,那么到这就可以打住了。cargo run既编译源码又运行可执行文件,那么还有一步需要被完成。即,使【C ABI动态链接库】对编译输出的.exe文件可见。否则,在应用程序启动过程中,会遇到(exit code: 0xc0000135, STATUS_DLL_NOT_FOUND)的错误和程序崩溃退出。其支持两种作法:C ABI动态链接库(文件)】至【编译输出.exe文件】所在文件夹内。Cargo Package根目录下,编写一个简单的build.rs构建脚本cargo,在编译过程中,在$OUT_DIR文件夹内(即,target\debug或target\release),创建一个指向【C ABI动态链接库(文件)】的【符号链接】。build.rs程序,可参考:use ::std::{env, fs, os, path::{Path, PathBuf}};fn main() { let out_dir = env::var("OUT_DIR").unwrap(); let work_dir = vec!["../../..", "../../../deps"];
work_dir.iter().for_each(|dir_path| symbolic_link_dll(&Path::new(&out_dir[..]).join(dir_path).canonicalize().unwrap()));
}#[cfg(windows)]fn symbolic_link_dll(exe_dir: &PathBuf) { const DLL_FILE: &str = "auxiliaries_native.dll"; let mut dll_origin = env::current_dir().unwrap();
dll_origin.push("assets");
dll_origin.push(DLL_FILE); if dll_origin.exists() { let dll_symbol = exe_dir.join(DLL_FILE); if dll_symbol.exists() {
fs::remove_file(dll_symbol.clone()).unwrap();
}
os::windows::fs::symlink_file(dll_origin.clone(), dll_symbol.clone()).unwrap();
}
}#[cfg(not(windows))]fn symbolic_link_dll(exe_dir: &PathBuf) { unreachable!("算是家庭作业,自己实现看看。其实,和`win32`的差不多!");
}
cargo run命令,完成:.exe可执行文件。C ABI动态链接库】文件和链接之。dll丢了、找不到了,程序直接崩溃退出 —— 连写日志的机会都没有。GUI错误提示框。啥都没有,难死我了!GUI主界面。Win32 GUI App — 体积绝对碾压electron(比性能,算我欺负你)。crate可带来的好处extern {...}块的简单粗暴,使用第三方crate(比如,dlopen)可带来的优势有两点:C ABI动态链接库】。这样,应用程序的启动与初始化延时会更短些。.dll后缀文件?”,而不是没头没脑地直接崩溃退出 — 特别是,禁用了console的【产品模式】真会导致什么崩溃线索都找不到。甲方还一口咬定一个文件都没有误删!太恶心了!dll给误删了。不是代码的错!”。Nice! 就是这个范儿!
.exe文件之外的。若遇到链接库文件丢失的情况,应用程序就不能正常运行了。.a文件】直接编译入.exe可执行文件内,来避免dll文件意外丢失的问题(当然,.exe文件的体积也会更大些)。但是,我正遇到了一个mingw64的编译错误undefined reference to 'BCryptGenRandom'还未搞定。若你对此也有兴趣,请待我的后续更新...原文作者:Rust语言中文社区;如有侵权,请联系管理员删除。