使用GCC将资源embedded到可执行文件中

我正在寻找一种轻松地将任何外部二进制数据embedded到由GCC编译的C / C ++应用程序中的方法。

一个很好的例子,我想要做的就是处理着色器代码 – 我可以把它保存在像const char* shader = "source here";这样的源文件中const char* shader = "source here"; 但这是非常不切实际的。

我希望编译器为我做这件事:在编译(链接阶段),阅读文件“foo.bar”,并将其内容链接到我的程序,以便我能够访问内容作为二进制数据从码。

对于我想要作为单个.exe文件分发的小应用程序可能会有用。

GCC支持这样的事情吗?

有几个可能性:

  • 使用ld的能力把任何文件转换成一个对象( 使用gcc mingwembedded二进制blob ):

     ld -r -b binary -o binary.o foo.bar # then link in binary.o 
  • 使用bin2c / bin2h实用程序将任何文件转换为字节数组( 代码中embedded图像,不使用资源部分或外部图像 )


更新:下面是一个更完整的示例,介绍如何使用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; } 

更新2 – 获取资源大小:我无法正确读取_binary_foo_bar_size。 在运行时,gdb通过使用display (unsigned int)&_binary_foo_bar_size文本资源的正确大小。 但是把这个分配给一个variables总是会有一个错误的值。 我可以通过以下方式解决这个问题:

 unsigned int iSize = (unsigned int)(&_binary_foo_bar_end - &_binary_foo_bar_start) 

这是一个解决方法,但它运作良好,并不太难看。

以及已经提到的build议,在Linux下,你可以使用hex转储工具xxd,它有一个function来生成一个C头文件:

 xxd -i mybinary > myheader.h 

不完全是一种新的方式,但肯定非常方便。 我偶然发现了这个完全免费的许可库,这里的答案中没有提到incbin汇编方法。

https://github.com/graphitemaster/incbin

回顾一下。 incbin方法就是这样。 你有一个thing.s汇编文件,你用gcc -c 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 + +与GCC:静态添加资源文件到可执行文件/库

但是上面的内容并不像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); } 

你可以在一个头文件中做到这一点:

 #ifndef SHADER_SRC_HPP #define SHADER_SRC_HPP const char* shader= " //source "; #endif 

只是包括这一点。

其他方法是读取着色器文件。