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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4158900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:39:49  来源:igfitidea点击:

Embedding resources in executable using GCC

c++cgccresourcesembedded-resource

提问by Kos

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

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

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.

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

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.

我希望编译器为我做这件事:在编译(链接阶段)时,读取文件“foo.bar”并将其内容链接到我的程序,以便我能够从代码。

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

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

Does GCC support something like this?

GCC 是否支持这样的东西?

回答by Michael Burr

There are a couple possibilities:

有几种可能性:



Update: Here's a more complete example of how to use data bound into the executable using 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;
}


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:

更新 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)

It is a workaround, but it works good and is not too ugly.

这是一种解决方法,但效果很好,而且不太难看。

回答by Riot

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:

除了已经提到的建议之外,在linux下你可以使用hex dump工具xxd,它有一个生成C头文件的功能:

xxd -i mybinary > myheader.h

回答by Matt

The .incbinGAS directivecan be used for this task. Here is a totally free licenced library that wraps around it:

.incbinGAS指令可用于这项任务。这是一个完全免费的许可库,环绕它:

https://github.com/graphitemaster/incbin

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

回顾一下。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

In your c or cpp code you can reference it with:

在你的 c 或 cpp 代码中,你可以引用它:

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

然后将生成的 .o 与其余的编译单元链接起来。归功于@John Ripley,他的回答在这里: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:

但是上面的没有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);   
}

回答by B?ови?

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.

另一种方法是读取着色器文件。