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

如何在Rust crate作为依赖时生成额外DLL构建产物?

整合Rust音频捕获项目为可发布库的实现方案

问题背景

原有项目包含两个crate:main-program(负责DLL注入与IPC音频接收)和patch(编译为带音频钩子的DLL,通过IPC发送数据)。现在需要将二者整合为my-audio-capture-lib,让用户添加依赖后,能直接调用capture_audio_from_pid捕获指定进程音频,且用户构建自身项目时自动生成所需的注入DLL。

实现步骤

1. 重构项目结构

将原patch的DLL代码移至my-audio-capture-lib/src/dll目录,原main-program的注入、IPC接收代码移至src/lib.rs作为库的核心API。最终结构如下:

my-audio-capture-lib/
├── src/
│   ├── lib.rs          # 主库代码:封装capture_audio_from_pid API
│   └── dll/
│       └── lib.rs      # 原patch的DLL钩子与IPC发送代码
├── Cargo.toml
└── build.rs            # 自动编译DLL的构建脚本

2. 配置Cargo.toml

在my-audio-capture-lib/Cargo.toml中定义两个编译目标:供用户依赖的常规Rust库,以及需要注入的DLL:

[package]
name = "my-audio-capture-lib"
version = "0.1.0"
edition = "2021"

# 主库:供用户依赖调用的常规Rust库
[lib]
name = "my_audio_capture_lib"
path = "src/lib.rs"
crate-type = ["rlib"]

# DLL目标:编译为注入用的动态链接库
[[lib]]
name = "audio_patch_dll"
path = "src/dll/lib.rs"
crate-type = ["cdylib"]
targets = ["x86_64-pc-windows-msvc", "i686-pc-windows-msvc"]

# Windows平台依赖(注入与IPC需要)
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["processthreadsapi", "memoryapi", "synchapi", "errhandlingapi"] }
interprocess = "1.2" # 可选:简化IPC实现

3. 编写build.rs自动编译DLL

在build.rs中添加逻辑,确保用户构建项目时自动编译DLL,并传递DLL路径给主库:

use std::env;
use std::process::Command;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let target = env::var("TARGET").unwrap();
    let profile = env::var("PROFILE").unwrap();

    // 编译DLL目标
    let status = Command::new("cargo")
        .arg("build")
        .arg("--lib")
        .arg("--target")
        .arg(&target)
        .arg(match profile.as_str() {
            "release" => "--release",
            _ => "",
        })
        .arg("--package")
        .arg("my-audio-capture-lib")
        .arg("--lib-name")
        .arg("audio_patch_dll")
        .current_dir(&crate_dir)
        .status()
        .expect("Failed to build audio patch DLL");

    assert!(status.success(), "DLL compilation failed");

    // 传递DLL路径给主库,通过环境变量
    let dll_path = format!(
        "{}/target/{}/{}/audio_patch_dll.dll",
        crate_dir,
        target,
        profile
    );
    println!("cargo:rustc-env=AUDIO_PATCH_DLL_PATH={}", dll_path);
}

4. 封装核心API

在src/lib.rs中实现capture_audio_from_pid函数,整合注入、IPC接收逻辑:

use std::env;
use std::error::Error;
use winapi::um::{processthreadsapi::OpenProcess, memoryapi::VirtualAllocEx, synchapi::CreateRemoteThread};

// 实现DLL注入逻辑(基于Windows API)
fn inject_dll(target_pid: u32, dll_path: &str) -> Result<(), Box<dyn Error>> {
    // 核心流程:
    // 1. 打开目标进程
    // 2. 在目标进程内存中分配空间写入DLL路径
    // 3. 创建远程线程调用LoadLibraryW加载DLL
    Ok(())
}

// 实现IPC音频接收逻辑(示例用命名管道)
fn receive_audio() -> impl Iterator<Item = Vec<i16>> {
    // 基于interprocess或原生Windows API实现IPC接收
    std::iter::empty()
}

/// 从指定PID的进程捕获音频
/// 返回音频数据迭代器,每个元素为一段PCM音频样本
pub fn capture_audio_from_pid(target_pid: u32) -> Result<impl Iterator<Item = Vec<i16>>, Box<dyn Error>> {
    // 获取自动编译的DLL路径
    let dll_path = env::var("AUDIO_PATCH_DLL_PATH")?;
    
    // 注入DLL到目标进程
    inject_dll(target_pid, &dll_path)?;
    
    // 建立IPC连接并返回音频流
    Ok(receive_audio())
}

5. 用户使用示例

用户只需在自身项目的Cargo.toml添加依赖:

[dependencies]
my-audio-capture-lib = "0.1.0"

然后在代码中调用API:

use my_audio_capture_lib::capture_audio_from_pid;

fn main() {
    let target_pid = 1234; // 替换为目标进程PID
    match capture_audio_from_pid(target_pid) {
        Ok(mut audio_stream) => {
            println!("开始捕获PID {}的音频", target_pid);
            for audio_data in audio_stream {
                // 处理音频数据(如保存、播放)
                println!("收到{}个音频样本", audio_data.len());
            }
        }
        Err(e) => eprintln!("捕获失败:{}", e),
    }
}

注意事项

  • 平台限制:仅支持Windows平台,需确保用户安装对应Rust目标(如rustup target add x86_64-pc-windows-msvc)。
  • 权限要求:注入DLL需要管理员权限,用户需以管理员身份运行程序。
  • IPC选择:推荐使用Windows命名管道或interprocess crate简化跨进程通信开发。

内容的提问来源于stack exchange,提问作者Nobbe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 01:39:18