我正在寻找一种方法来轻松地将任何外部二进制数据嵌入到由GCC编译的C / C ++应用程序中。
我想要做的一个很好的例子是处理着色器代码 - 我可以将它保存在像const char* shader = "source here";
这样的源文件中,但这是非常不切实际的。
我希望编译器为我做这件事:在编译(链接阶段)时,读取文件“foo.bar”并将其内容链接到我的程序,这样我就能够以二进制形式访问内容来自代码的数据。
对于我想将其作为单个.exe文件分发的小型应用程序非常有用。
GCC是否支持这样的事情?
答案 0 :(得分:43)
有几种可能性:
使用ld的功能将任何文件转换为对象(Embedding binary blobs using gcc mingw):
ld -r -b binary -o binary.o foo.bar # then link in binary.o
使用bin2c
/ bin2h
实用程序将任何文件转换为字节数组(Embed image in code, without using resource section or external images)
更新:以下是如何使用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;
}
更新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)
这是一种解决方法,但它运作良好且不太难看。
答案 1 :(得分:20)
除了已经提到的建议,在linux下你可以使用十六进制转储工具xxd,它具有生成C头文件的功能:
xxd -i mybinary > myheader.h
答案 2 :(得分:7)
.incbin
GAS directive可用于此任务。这是一个包含它的完全免费的许可库:
https://github.com/graphitemaster/incbin
回顾一下。 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
在c或cpp代码中,您可以参考:
extern const char thing[];
extern const char* thing_end;
extern int thing_size;
然后,将生成的.o与其余的编译单元链接起来。 @John Ripley在这里给出答案:C/C++ with GCC: Statically add resource files to executable/library
但是上面的内容并不像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);
}
答案 3 :(得分:0)
您可以在头文件中执行此操作:
#ifndef SHADER_SRC_HPP
#define SHADER_SRC_HPP
const char* shader= "
//source
";
#endif
并且只包括它。
其他方法是读取着色器文件。