目录
1.简介
如果你在C++项目里需要调用另一个程序------比如用FFmpeg转码视频、用ImageMagick处理图片,或者启动一个Python脚本------肯定经历过跨平台进程调用的痛苦。Windows的CreateProcess和Unix的fork/exec完全两套API,还要处理管道、等待、错误码......光是让程序在不同系统上都能运行就得写一堆条件编译。
这时候,tiny-process-library 就像给你配了个万能的"程序启动管家"。它是一个单头文件的C++库,专门解决一件事:用统一的API在Windows、Linux、macOS上启动和管理外部进程,而且代码量极小,集成起来毫无负担。
它的特点有:
- 接口简洁,易于使用
- 支持同步 / 异步执行外部命令
- 支持捕获子进程的 stdout/stderr 输出
- 支持设置子进程的工作目录
- 支持终止子进程
2.安装与集成
1.手动集成(推荐新手)
- 将源码中的
process.hpp、process.cpp(Windows 还需process_win.cpp,Linux/macOS 需process_unix.cpp)复制到你的项目目录 - 直接包含头文件即可使用
2.源码编译成库集成
cpp
git clone http://gitlab.com/eidheim/tiny-process-library
cd tiny-process-library
mkdir build
cd build
cmake ..
make
./examples
3.CMake集成
如果你的项目使用 CMake,可以通过 add_subdirectory 集成:
cpp
# 添加库目录
add_subdirectory(tiny-process-library)
# 链接库
target_link_libraries(你的项目名 tiny-process-library)
3.核心使用示例
1.基础同步执行(阻塞等待进程结束)
执行一个简单命令,等待执行完成并获取退出码:
cpp
#include "process.hpp"
#include <iostream>
int main() {
// 执行命令:Windows 用 "cmd /c echo hello",Linux/macOS 用 "echo hello"
#ifdef _WIN32
TinyProcessLib::Process process("cmd /c echo hello world", ".");
#else
TinyProcessLib::Process process("echo hello world", ".");
#endif
// 阻塞等待进程结束,获取退出码
int exit_code = process.get_exit_status();
std::cout << "进程退出码: " << exit_code << std::endl;
return 0;
}
Process构造函数第一个参数是要执行的命令,第二个是工作目录(.表示当前目录)get_exit_status()是阻塞函数,会等待进程执行完成后返回退出码(0 表示成功)
2.异步执行 + 捕获输出(最常用)
异步执行命令,实时捕获 stdout/stderr 输出,不阻塞主线程:
cpp
#include "process.hpp"
#include <iostream>
#include <string>
int main() {
// 存储输出的变量
std::string output, error;
#ifdef _WIN32
// Windows 执行 dir 命令
TinyProcessLib::Process process(
"cmd /c dir",
".",
[&output](const char* data, size_t size) { // stdout 回调
output.append(data, size);
},
[&error](const char* data, size_t size) { // stderr 回调
error.append(data, size);
}
);
#else
// Linux/macOS 执行 ls -l 命令
TinyProcessLib::Process process(
"ls -l",
".",
[&output](const char* data, size_t size) { // stdout 回调
output.append(data, size);
},
[&error](const char* data, size_t size) { // stderr 回调
error.append(data, size);
}
);
#endif
// 异步等待(非阻塞,也可以用 wait() 阻塞)
while (!process.try_get_exit_status()) {
// 主线程可以做其他事情
std::cout << "进程还在运行..." << std::endl;
// 休眠 500ms,避免循环过快
#ifdef _WIN32
Sleep(500);
#else
usleep(500000);
#endif
}
// 输出结果
std::cout << "=== 标准输出 ===" << std::endl;
std::cout << output << std::endl;
std::cout << "=== 错误输出 ===" << std::endl;
std::cout << error << std::endl;
return 0;
}
- 第三个参数是
stdout回调函数,子进程输出时会触发,参数是输出数据和长度 - 第四个参数是
stderr回调函数,捕获错误输出 try_get_exit_status()是非阻塞检查进程是否结束,返回true表示进程已结束- 回调函数是在子线程中执行的,注意线程安全(比如多线程操作同一个变量时加锁)
3.终止子进程
主动终止正在运行的子进程:
cpp
#include "process.hpp"
#include <iostream>
#include <chrono>
#include <thread>
int main() {
#ifdef _WIN32
TinyProcessLib::Process process("cmd /c ping -n 10 127.0.0.1", ".");
#else
TinyProcessLib::Process process("ping -c 10 127.0.0.1", ".");
#endif
// 运行 3 秒后终止进程
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "终止子进程..." << std::endl;
process.kill(); // 终止进程
// 等待进程完全退出
int exit_code = process.get_exit_status();
std::cout << "进程退出码: " << exit_code << std::endl;
return 0;
}
kill()方法会强制终止子进程(Windows 下调用TerminateProcess,Linux/macOS 下发送SIGKILL)- 终止后仍需调用
get_exit_status()释放资源
4.设置环境变量
给子进程设置自定义环境变量:
cpp
#include "process.hpp"
#include <iostream>
#include <vector>
#include <string>
int main() {
// 构造环境变量列表(格式:KEY=VALUE)
std::vector<std::string> env = {"MY_VAR=hello_tiny_process", "PATH=/usr/bin"};
#ifdef _WIN32
TinyProcessLib::Process process(
"cmd /c echo %MY_VAR%", // Windows 读取环境变量
".",
[](const char* data, size_t size) {
std::cout << "输出: " << std::string(data, size) << std::endl;
},
nullptr,
env // 传入自定义环境变量
);
#else
TinyProcessLib::Process process(
"echo $MY_VAR", // Linux/macOS 读取环境变量
".",
[](const char* data, size_t size) {
std::cout << "输出: " << std::string(data, size) << std::endl;
},
nullptr,
env // 传入自定义环境变量
);
#endif
process.get_exit_status();
return 0;
}
4.跨平台注意事项
- 命令格式差异 :
- Windows 下执行普通命令需要通过
cmd /c 命令(比如cmd /c dir) - Linux/macOS 下直接执行命令(比如
ls -l)
- Windows 下执行普通命令需要通过
- 路径分隔符 :Windows 用
\,Linux/macOS 用/,建议用std::filesystem处理路径 - 编码问题:Windows 下默认是 GBK 编码,Linux/macOS 是 UTF-8,捕获输出时注意编码转换
5.常见问题解决
- 进程创建失败 :
- 检查命令是否存在(比如 Windows 下有没有
ping.exe) - 检查工作目录是否存在
- 检查命令是否存在(比如 Windows 下有没有
- 输出乱码(Windows) :
- 将命令输出转为 UTF-8,比如
cmd /c chcp 65001 && dir(65001 是 UTF-8 代码页)
- 将命令输出转为 UTF-8,比如
- 回调函数不执行 :
- 确保进程有输出,且没有提前终止进程
- 回调函数是异步的,主线程不要过早退出
6.总结
tiny-process-library核心是Process类,支持同步 / 异步执行命令、捕获输出、终止进程,跨平台使用需注意命令格式差异。- 异步执行时通过回调函数捕获
stdout/stderr,注意线程安全;同步执行用get_exit_status()阻塞等待。 - 跨平台开发时,用条件编译区分 Windows/Linux/macOS 的命令和路径格式,避免兼容性问题。