C++ 使用 GCC 在可执行文件中嵌入资源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4158900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Embedding resources in executable using GCC
提问by Kos
I'm looking for a way to easily embed any external binary data in a C/C++ application compiled by GCC.
我正在寻找一种方法来轻松地将任何外部二进制数据嵌入到 GCC 编译的 C/C++ 应用程序中。
A good example of what I'd like to do is handling shader code - I can just keep it in source files like const char* shader = "source here";
but that's extremely impractical.
我想做的一个很好的例子是处理着色器代码 - 我可以将它保存在源文件中,const char* shader = "source here";
但这是非常不切实际的。
I'd like the compiler to do it for me: upon compilation (linking stage), read file "foo.bar" and link its content to my program, so that I'd be able to access the contents as binary data from the code.
我希望编译器为我做这件事:在编译(链接阶段)时,读取文件“foo.bar”并将其内容链接到我的程序,以便我能够从代码。
Could be useful for small applications which I'd like to distribute as a single .exe file.
对于我想作为单个 .exe 文件分发的小型应用程序可能很有用。
Does GCC support something like this?
GCC 是否支持这样的东西?
回答by Michael Burr
There are a couple possibilities:
有几种可能性:
use ld's capability to turn any file into an object (Embedding binary blobs using gcc mingw):
ld -r -b binary -o binary.o foo.bar # then link in binary.o
use a
bin2c
/bin2h
utility to turn any file into an array of bytes (Embed image in code, without using resource section or external images)
使用 ld 的功能将任何文件转换为对象(使用 gcc mingw 嵌入二进制 blob):
ld -r -b binary -o binary.o foo.bar # then link in binary.o
使用
bin2c
/bin2h
实用程序将任何文件转换为字节数组(在代码中嵌入图像,不使用资源部分或外部图像)
Update: Here's a more complete example of how to use data bound into the executable using ld -r -b binary
:
更新:这是一个更完整的示例,说明如何使用绑定到可执行文件中的数据ld -r -b binary
:
#include <stdio.h>
// a file named foo.bar with some example text is 'imported' into
// an object file using the following command:
//
// ld -r -b binary -o foo.bar.o foo.bar
//
// That creates an bject file named "foo.bar.o" with the following
// symbols:
//
// _binary_foo_bar_start
// _binary_foo_bar_end
// _binary_foo_bar_size
//
// Note that the symbols are addresses (so for example, to get the
// size value, you have to get the address of the _binary_foo_bar_size
// symbol).
//
// In my example, foo.bar is a simple text file, and this program will
// dump the contents of that file which has been linked in by specifying
// foo.bar.o as an object file input to the linker when the progrma is built
extern char _binary_foo_bar_start[];
extern char _binary_foo_bar_end[];
int main(void)
{
printf( "address of start: %p\n", &_binary_foo_bar_start);
printf( "address of end: %p\n", &_binary_foo_bar_end);
for (char* p = _binary_foo_bar_start; p != _binary_foo_bar_end; ++p) {
putchar( *p);
}
return 0;
}
Update 2 - Getting the resource size: I could not read the _binary_foo_bar_size correctly. At runtime, gdb shows me the right size of the text resource by using display (unsigned int)&_binary_foo_bar_size
. But assigning this to a variable gave always a wrong value. I could solve this issue the following way:
更新 2 - 获取资源大小:我无法正确读取 _binary_foo_bar_size。在运行时,gdb 使用display (unsigned int)&_binary_foo_bar_size
. 但是将其分配给变量总是给出错误的值。我可以通过以下方式解决这个问题:
unsigned int iSize = (unsigned int)(&_binary_foo_bar_end - &_binary_foo_bar_start)
It is a workaround, but it works good and is not too ugly.
这是一种解决方法,但效果很好,而且不太难看。
回答by Riot
As well as the suggestions already mentioned, under linux you can use the hex dump tool xxd, which has a feature to generate a C header file:
除了已经提到的建议之外,在linux下你可以使用hex dump工具xxd,它有一个生成C头文件的功能:
xxd -i mybinary > myheader.h
回答by Matt
The .incbin
GAS directivecan be used for this task. Here is a totally free licenced library that wraps around it:
该.incbin
GAS指令可用于这项任务。这是一个完全免费的许可库,环绕它:
https://github.com/graphitemaster/incbin
https://github.com/graphitemaster/incbin
To recap. The incbin method is like this. You have a thing.s assembly file that you compile with gcc -c thing.s
回顾一下。incbin 方法是这样的。您有一个用 gcc -c thing.s 编译的 thing.s 程序集文件
.section .rodata
.global thing
.type thing, @object
.align 4
thing:
.incbin "meh.bin"
thing_end:
.global thing_size
.type thing_size, @object
.align 4
thing_size:
.int thing_end - thing
In your c or cpp code you can reference it with:
在你的 c 或 cpp 代码中,你可以引用它:
extern const char thing[];
extern const char* thing_end;
extern int thing_size;
So then you link the resulting .o with the rest of the compilation units. Credit where due is to @John Ripley with his answer here: C/C++ with GCC: Statically add resource files to executable/library
然后将生成的 .o 与其余的编译单元链接起来。归功于@John Ripley,他的回答在这里:C/C++ with GCC: Statically add resource files to executable/library
But the above is not as convenient as what incbin can give you. To accomplish the above with incbin you don't need to write any assembler. Just the following will do:
但是上面的没有incbin给你的方便。要使用 incbin 完成上述操作,您无需编写任何汇编程序。只需执行以下操作:
#include "incbin.h"
INCBIN(thing, "meh.bin");
int main(int argc, char* argv[])
{
// Now use thing
printf("thing=%p\n", gThingData);
printf("thing len=%d\n", gThingSize);
}
回答by B?ови?
You could do this in a header file :
您可以在头文件中执行此操作:
#ifndef SHADER_SRC_HPP
#define SHADER_SRC_HPP
const char* shader= "
//source
";
#endif
and just include that.
并包括在内。
Other way is to read the shader file.
另一种方法是读取着色器文件。