这个小Demo演示了如何使用Rust调用DLL内的函数,将获取到的内容复制到系统粘贴板
这个是做什么的呢,前段时间,我用Python写一个小工具,用来读取DLL文件获取设备的标识码,打包成exe后运行起来有点慢,正好在学习Rust,打算用Rust写一个,于是东拼西凑的鼓捣出来,在写的过程中,想到能不能只分发给使用人员一个exe文件,而不用一起发送DLL呢,这样也不用打包分发
搜索了一番,发现似乎不能把DLL文件集成在exe中运行,但是了解到可以换个思路,Rust是可以加载资源到EXE成为静态内容的,如果在编译的过程中,将DLL加载到EXE中,然后运行exe的时候,如果当前目录中有DLL文件,直接调用使用,如果没有DLL文件,运行时生成一个再使用,也是曲线救国的一个思路
extern crate clipboard;
use clipboard::ClipboardProvider;
use clipboard::ClipboardContext;
extern crate libloading;
use libloading::{Library, Symbol};
use std::io::prelude::*;
use std::path::Path;
use std::ffi::CStr;
use std::fs::File;
use std::str;
use std::io;
type GetHylinkDeviceId = unsafe fn() -> *const i8;
const LIBRARY_PATH: &'static str = "PcInfo.dll";
const HYLINK_DLL: &'static [u8] = include_bytes!("PcInfo.dll");
fn generate_hylink_dll(filename: &str, buf: &[u8]) -> io::Result<()> {
let mut f = try!(File::create(filename));
try!(f.write(&buf));
Ok(())
}
fn copy_to_clipboard(x3id: String) {
let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap();
println!("{:?}", ctx.get_contents());
ctx.set_contents(x3id).unwrap();
}
fn get_x3id() -> String {
// 如果不存在DLL文件,生成DLL
if !Path::new(LIBRARY_PATH).exists() {
match generate_hylink_dll(LIBRARY_PATH, HYLINK_DLL) {
Ok(s) => println!("Generate hylink dll file success {:?}", s),
Err(r) => println!("Generate hylink dll file failed {:?}", r),
}
}
// 从本地加载DLL文件
let lib = Library::new(LIBRARY_PATH).unwrap();
println!("{:?}", lib);
// 调用DLL获取标识码
let x3id = unsafe {
let func: Symbol<GetHylinkDeviceId> = lib.get(b"GetHylinkDeviceId").unwrap();
let c_buf: *const i8 = func();
let c_str: &CStr = CStr::from_ptr(c_buf);
let str_slice: &str = c_str.to_str().unwrap();
let str_buf: String = str_slice.to_owned();
str_buf
};
x3id
}
fn main() {
// 从DLL中获取X3标识码
let x3id: String = get_x3id();
println!("{:?}", x3id);
// 将标识码复制到粘贴板
copy_to_clipboard(x3id)
}
Cargo.toml
[dependencies]
libloading = "0.4"
clipboard = { git = "https://github.com/aweinstock314/rust-clipboard.git" }