使用GCC在可执行文件中嵌入资源

时间:2010-11-11 20:21:31

标签: c++ c gcc resources embedded-resource

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

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

我希望编译器为我做这件事:在编译(链接阶段)时,读取文件“foo.bar”并将其内容链接到我的程序,这样我就能够以二进制形式访问内容来自代码的数据。

对于我想将其作为单个.exe文件分发的小型应用程序非常有用。

GCC是否支持这样的事情?

4 个答案:

答案 0 :(得分:43)

有几种可能性:


更新:以下是如何使用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

并且只包括它。

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