GCCでコンパイルされたC/C++アプリケーションに外部バイナリデータを簡単に埋め込む方法を探しています。
私がやりたいことの良い例は、シェーダーコードの処理です-const char* shader = "source here";
しかし、それは非常に非現実的です。
コンパイラーに実行してもらいたい:コンパイル(リンク段階)で、ファイル「foo.bar」を読み取り、そのコンテンツをプログラムにリンクして、コンテンツからバイナリデータとしてコンテンツにアクセスできるようにします。コード。
単一の.exeファイルとして配布したい小さなアプリケーションに役立ちます。
GCCはこのようなものをサポートしていますか?
いくつかの可能性があります:
ldの機能を使用して、任意のファイルをオブジェクトに変換します( gcc mingwを使用してバイナリblobを埋め込む ):
_ld -r -b binary -o binary.o foo.bar # then link in binary.o
_
_bin2c
_/_bin2h
_ユーティリティを使用して、任意のファイルをバイトの配列に変換します( リソースセクションまたは外部イメージを使用せずにコードに埋め込みイメージ )
更新:_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)
_
これは回避策ですが、うまく機能し、見苦しくありません。
すでに述べた提案の他に、Linuxでは、Cヘッダーファイルを生成する機能を持つ16進ダンプツールxxdを使用できます。
xxd -i mybinary > myheader.h
.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);
}
ヘッダーファイルでこれを行うことができます:
#ifndef SHADER_SRC_HPP
#define SHADER_SRC_HPP
const char* shader= "
//source
";
#endif
それを含めてください。
他の方法は、シェーダーファイルを読み取ることです。