これを行う最も簡単な方法の 1 つは、リソースを読み取り、リソース データの長さと実際のリソース データを定数文字リテラルの配列として含む C ファイルを生成する、小さく移植可能な C プログラムをビルドに含めることです。これは完全にプラットフォームに依存しませんが、適度に小さいリソースにのみ使用する必要があります。より大きなリソースの場合、おそらくプログラムにファイルを埋め込みたくないでしょう。
リソース「foo」の場合、生成された C ファイル「foo.c」には以下が含まれます。
const char foo[] = { /* bytes of resource foo */ };
const size_t foo_len = sizeof(foo);
C++ からリソースにアクセスするには、次の 2 つのシンボルを使用するヘッダーまたは cpp ファイルで宣言します。
extern "C" const char foo[];
extern "C" const size_t foo_len;
ビルドで生成するfoo.c
には、C プログラムのターゲット (embedfile.c と呼ぶ) が必要で、ADD_CUSTOM_COMMANDコマンドを使用してこのプログラムを呼び出す必要があります。
add_executable(embedfile embedfile.c)
add_custom_command(
OUTPUT foo.c
COMMAND embedfile foo foo.rsrc
DEPENDS foo.rsrc)
次に、foo.c
「foo」リソースを必要とするターゲットのソース リストに含めます。「foo」のバイトにアクセスできるようになりました。
プログラムembedfile.cは次のとおりです。
#include <stdlib.h>
#include <stdio.h>
FILE* open_or_exit(const char* fname, const char* mode)
{
FILE* f = fopen(fname, mode);
if (f == NULL) {
perror(fname);
exit(EXIT_FAILURE);
}
return f;
}
int main(int argc, char** argv)
{
if (argc < 3) {
fprintf(stderr, "USAGE: %s {sym} {rsrc}\n\n"
" Creates {sym}.c from the contents of {rsrc}\n",
argv[0]);
return EXIT_FAILURE;
}
const char* sym = argv[1];
FILE* in = open_or_exit(argv[2], "r");
char symfile[256];
snprintf(symfile, sizeof(symfile), "%s.c", sym);
FILE* out = open_or_exit(symfile,"w");
fprintf(out, "#include <stdlib.h>\n");
fprintf(out, "const char %s[] = {\n", sym);
unsigned char buf[256];
size_t nread = 0;
size_t linecount = 0;
do {
nread = fread(buf, 1, sizeof(buf), in);
size_t i;
for (i=0; i < nread; i++) {
fprintf(out, "0x%02x, ", buf[i]);
if (++linecount == 10) { fprintf(out, "\n"); linecount = 0; }
}
} while (nread > 0);
if (linecount > 0) fprintf(out, "\n");
fprintf(out, "};\n");
fprintf(out, "const size_t %s_len = sizeof(%s);\n\n",sym,sym);
fclose(in);
fclose(out);
return EXIT_SUCCESS;
}