Embedding resources in executable using GCC

前端 未结 4 1670
小鲜肉
小鲜肉 2020-11-22 16:21

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

A good example of what I\'d like to do is handling shader cod

相关标签:
4条回答
  • 2020-11-22 16:52

    The .incbin GAS directive can be used for this task. Here is a totally free licenced library that wraps around it:

    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

          .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:

    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

    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:

    #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);   
    }
    
    0 讨论(0)
  • 2020-11-22 17:04

    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:

    xxd -i mybinary > myheader.h
    
    0 讨论(0)
  • 2020-11-22 17:07

    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)


    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\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:

    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.

    0 讨论(0)
  • 2020-11-22 17:08

    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.

    0 讨论(0)
提交回复
热议问题