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

2021-12-02 00:00:00 gcc c resources c++ embedded-resource

我正在寻找一种方法,可以在 GCC 编译的 C/C++ 应用程序中轻松嵌入任何外部二进制数据.

I'm looking for a way to easily embed any external binary data in a C/C++ application compiled by GCC.

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

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.

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

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.

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

Could be useful for small applications which I'd like to distribute as a single .exe file.

GCC 是否支持这样的东西?

Does GCC support something like this?

推荐答案

有几种可能性:

  • 使用 ld 的功能将任何文件转换为对象(嵌入二进制 blob使用 gcc mingw):

ld -r -b binary -o binary.o foo.bar  # then link in binary.o

  • 使用 bin2c/bin2h 实用程序将任何文件转换为字节数组 (在代码中嵌入图片,不使用资源部分或外部图片)

  • 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 -r -b binary绑定到可执行文件中的数据:

    Update: Here's a more complete example of how to use data bound into the executable using 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
    ", &_binary_foo_bar_start);
        printf( "address of end: %p
    ", &_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 向我显示文本资源的正确大小.但是将其分配给变量总是给出错误的值.我可以通过以下方式解决这个问题:


    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:

    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.

  • 相关文章