web-dev-qa-db-ja.com

GCCを使用して実行可能ファイルにリソースを埋め込む

GCCでコンパイルされたC/C++アプリケーションに外部バイナリデータを簡単に埋め込む方法を探しています。

私がやりたいことの良い例は、シェーダーコードの処理です-const char* shader = "source here";しかし、それは非常に非現実的です。

コンパイラーに実行してもらいたい:コンパイル(リンク段階)で、ファイル「foo.bar」を読み取り、そのコンテンツをプログラムにリンクして、コンテンツからバイナリデータとしてコンテンツにアクセスできるようにします。コード。

単一の.exeファイルとして配布したい小さなアプリケーションに役立ちます。

GCCはこのようなものをサポートしていますか?

51
Kos

いくつかの可能性があります:


更新:_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-リソースサイズの取得:_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)
_

これは回避策ですが、うまく機能し、見苦しくありません。

43
Michael Burr

すでに述べた提案の他に、Linuxでは、Cヘッダーファイルを生成する機能を持つ16進ダンプツールxxdを使用できます。

xxd -i mybinary > myheader.h
21
Riot

.incbin GASディレクティブ をこのタスクに使用できます。以下は、それを包む完全に無料のライセンスライブラリです。

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がここで答えたクレジット: GCCを使用したC/C++:実行可能ファイル/ライブラリにリソースファイルを静的に追加

しかし、上記は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);   
}
7
Matt

ヘッダーファイルでこれを行うことができます:

#ifndef SHADER_SRC_HPP
#define SHADER_SRC_HPP
const char* shader= "

//source

";
#endif

それを含めてください。

他の方法は、シェーダーファイルを読み取ることです。

0
BЈовић