我该如何把文件打包并嵌入到我的可执行文件中,然后在运行时访问它们?
我正在写一个小程序,它需要加载并使用一个数据文件(例如字体、预计算的查找表等)。但我不想在构建完成后、安装或部署这款程序时还去担心这个文件到底放在什么位置。因此我的想法是,设法在不实际打开文件的情况下获取数据,也就是说让数据以某种方式成为程序的一部分。
我可以直接定义一个字节的静态数组:
static std::byte my_data[] = { 0x12, 0x34, /* whatever */ };
这也能工作,但这非常麻烦。因此,在程序的源代码层面,我确实想要一个单独的文件,我们把它叫作 foo.bin。我希望有一种办法把 foo.bin 放进我的可执行文件里,然后在运行时访问它——要么它已经被加载,要么很容易加载,而不需要我的代码去开始解析二进制文件。我相信这是可能的,因为可执行文件并非单块,它们由“段”组成。
我该如何着手?我在问的是“对接”的两端:在构建时把我的文件嵌入到可执行文件中的方式,以及在运行时访问它的方式。
注释:
- 我还没见过有这类做法的程序,但如果这在某些(类型的)程序中确实很常见,我大概会愿意遵循行业惯例。
- 如果可能,我更偏好一种可移植的方法,但我意识到可能不存在,因为C++标准并没有提供这样的功能,而不同操作系统的可执行文件也各不相同。所以我最关注的是GNU/Linux + ELF环境,但如果你只能给出Windows或 macOS的答案,那也有用。
- 如果可行,最好能在不运行可执行文件的情况下就能从可执行文件中轻松提取数据文件,即使用在命令行中可用的工具。
- 依赖更新的C++标准特性是可以理解的,但如果可以将其限制在较旧的版本,或维持在C++11,会更好。
解决方案
自C23起有一个新特性 #embed。
Gcc 15支持它: GCC 15 Release Series — Changes, New Features, and Fixes - GNU Project
还实现了更多的C23功能:
#embedpreprocessing directive support。
Clang 19也 有这个功能。
MSVC我暂时还没看到有这个特性,但可能将来会有。
还没尝试过。
它也属于 C++26 的内容。
#include <iostream>
constexpr char test[] = {
#embed "test.data" if_empty('M', 'i', 's', 's', 'i', 'n', 'g') suffix(, '\0')
};
int main()
{
std::cout << test << '\n';
}
来自clang的警告:warning: #embed is a Clang extension [-Wc23-extensions],
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。