2016-03-19 15 views
0

私は、端末だけでライブラリを作成する方法を学んでいます。 NSBundleのように、画像、テキスト、APIキーなどのリソースを静的にリンクされたアーカイブファイルに配置することは可能ですか?これらのリソースはどのように参照するのですか?静的ライブラリへの埋め込みリソース - C/C++

+0

これは標準的なリンカー関数ではなく、標準的な方法はありません。しかし、スタティックリソースの埋め込みをライブラリにもサポートするリンカがかなりあります。あなたはOSと開発環境を指定していないので、あなたの質問に答えることはできません。 – tofro

+0

@tofro私が使用しているOSはPOSIXですが、可能ならば移植可能なものを望んでいました。推奨できるリンカーはありますか? –

+0

*本当に*ポータブルなものをお探しの場合:* const unsigned char blob [] = {0x0,022、.....} *のようなバイナリデータからCコードを作成する独自のコンバータを作成してください。コンパイルとリンク。それほど難しいことではありません。それ以外のものは持ち運びできません。 – tofro

答えて

0

あなたがしたいことは、バイナリブロブからリンクできるようにするために、バイナリブロブからオブジェクトファイルを作成することです。プログラムの残りの部分でバイナリデータを扱いたいので、にはが少なくとも1つのシンボル(おそらくBLOBの先頭)を持つシンボルテーブルを含むオブジェクトファイルである必要があります。

オブジェクトファイルは完全にシステムに依存しているため、実際に直接実行する移植性のある方法はありません。たとえば、Linuxでは、かなり長い間、少なくとも2つの異なるオブジェクトファイル形式を使用していました。

最もポータブル(と、多分、最も単純な)方法は、それを行うには:Cコンパイラ:あなたのdevの環境に合わせてオブジェクトファイルを構築する方法を知っているツールを使用してください。

const unsigned char blob[] = {0x0,0x22,.....}; 

その後コンパイルとリンクのように、あなたのバイナリデータからCコードを生成し、独自のコンバータを書きます。あまりにも難しいことではなく、むしろ10分の仕事です。他のすべては完全に移植性がありません。

GNU objcopyが利用可能なプラットフォームでは、これは別の方法です。 (入力ファイル形式として 'バイナリ'を指定し、オブジェクトファイル形式を出力先に指定します。また、 "--add-symbol"を使用してBLOBの開始シンボルを追加する必要があります)。 POSIXシステムで

0

、あなたはかなり標準のシェルsh、4つの非常に便利なシェルrmと呼ばれるユーティリティ、printfod、およびsedを持っています。

のは、あなたがバイナリファイルfoo.barの内容を含むconst unsigned char blob[]配列を持つファイルfoo.cを作成したいとしましょう:

export LANG=C LC_ALL=C 
rm -f foo.c 
printf 'const unsigned char blob[] = {\n' > foo.c 
od -A n -t x1 foo.bar | sed -e 's| *\([0-9A-Fa-f][0-9A-Fa-f]\)| 0x\1U,|g; s|^| |' >> foo.c 
printf '};\n' >> foo.c 

最初の行はCにロケールを設定します。これにより、ユーティリティは、一部のローカライズされたバリアントではなく、期待どおりのフォーマットを使用するようになります。

2行目は、おそらく既存のfoo.cを削除します。 (ファイルを追加しないで既存のファイルに出力すると、いくつかのシェルが文句を言う場合があります)。-fは、ファイルがまだ存在しない場合でも不平を解決します。

3行目と5行目は、配列定義と終了をfoo.cファイルに追加します。

4行目はodユーティリティを使用して、foo.barの内容を16進数のバイトとして出力します。 sedを使用して0xを追加し、それぞれの16進バイトにU,を追加して、素敵できれいなCにしてから、行に3つのスペースを追加します(4つのスペースで字下げします)。

このアプローチが気に入らない場合は、これを行うための独自のユーティリティをいつでも書くことができます。例えば:上記のコードで の#includeの#include の#includeの#include

#ifndef DEFAULT_VARNAME 
#define DEFAULT_VARNAME "blob" 
#endif 

#ifndef DEFAULT_STORAGE 
#define DEFAULT_STORAGE "const" 
#endif 

#ifndef DEFAULT_ATTRIBUTES 
#define DEFAULT_ATTRIBUTES "" 
#endif 

#ifndef DEFAULT_INDENT 
#define DEFAULT_INDENT " " 
#endif 

#ifndef DEFAULT_COLUMNS 
#define DEFAULT_COLUMNS 16 
#endif 

int usage(const char *argv0) 
{ 
    fprintf(stderr, "\n"); 
    fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv0); 
    fprintf(stderr, "  %s [ OPTIONS ] file [ [ OPTIONS ] file .. ]\n", argv0); 
    fprintf(stderr, "\n"); 
    fprintf(stderr, "Options:\n"); 
    fprintf(stderr, "  -n %-10s Variable name\n", "'" DEFAULT_VARNAME "'"); 
    fprintf(stderr, "  -s %-10s Storage type\n", "'" DEFAULT_STORAGE "'"); 
    fprintf(stderr, "  -a %-10s Attributes\n", "'" DEFAULT_ATTRIBUTES "'"); 
    fprintf(stderr, "  -i %-10s Indentation\n", "'" DEFAULT_INDENT "'"); 
    fprintf(stderr, "  -c %-10d Bytes per line\n", (int)DEFAULT_COLUMNS); 
    fprintf(stderr, "\n"); 
    fprintf(stderr, "This program will output the contents of the specified file(s)\n"); 
    fprintf(stderr, "as C source code.\n"); 
    fprintf(stderr, "\n"); 
    return EXIT_SUCCESS; 
} 


int main(int argc, char *argv[]) 
{ 
    const char *storage = DEFAULT_STORAGE; 
    const char *varname = DEFAULT_VARNAME; 
    const char *attributes = DEFAULT_ATTRIBUTES; 
    const char *indent = DEFAULT_INDENT; 
    size_t  columns = DEFAULT_COLUMNS; 

    FILE *in; 
    size_t bytes; 
    int  ch, arg; 
    char dummy; 

    if (argc < 2) 
     return usage(argv[0]); 

    arg = 1; 
    while (arg < argc) { 

     if (argv[arg][0] == '-') { 
      if (argv[arg][1] == 'n') { 
       if (argv[arg][2] != '\0') { 
        varname = argv[arg] + 2; 
        arg++; 
        continue; 
       } else 
       if (arg + 1 < argc) { 
        varname = argv[arg + 1]; 
        arg += 2; 
        continue; 
       } 
      } else 
      if (argv[arg][1] == 's') { 
       if (argv[arg][2] != '\0') { 
        storage = argv[arg] + 2; 
        arg++; 
        continue; 
       } else 
       if (arg + 1 < argc) { 
        storage = argv[arg + 1]; 
        arg += 2; 
        continue; 
       } 
      } else 
      if (argv[arg][1] == 'a') { 
       if (argv[arg][2] != '\0') { 
        attributes = argv[arg] + 2; 
        arg++; 
        continue; 
       } else 
       if (arg + 1 < argc) { 
        attributes = argv[arg + 1]; 
        arg += 2; 
        continue; 
       } 
      } else 
      if (argv[arg][1] == 'i') { 
       if (argv[arg][2] != '\0') { 
        indent = argv[arg] + 2; 
        arg++; 
        continue; 
       } else 
       if (arg + 1 < argc) { 
        indent = argv[arg + 1]; 
        arg += 2; 
        continue; 
       } 
      } else 
      if (argv[arg][1] == 'c') { 
       if (argv[arg][2] != '\0') { 
        if (sscanf(argv[arg] + 2, " %zu %c", &columns, &dummy) != 1 || columns < 1) { 
         fprintf(stderr, "%s: Invalid number of bytes per line.\n", argv[arg] + 2); 
         return EXIT_FAILURE; 
        } 
        arg++; 
        continue; 
       } else 
       if (arg + 1 < argc) { 
        if (sscanf(argv[arg+1], " %zu %c", &columns, &dummy) != 1 || columns < 1) { 
         fprintf(stderr, "%s: Invalid number of bytes per line.\n", argv[arg + 1]); 
         return EXIT_FAILURE; 
        } 
        arg += 2; 
        continue; 
       } 
      } else 
      if (!strcmp(argv[arg], "-h") || !strcmp(argv[arg], "--help")) 
       return usage(argv[0]); 
     } 

     in = fopen(argv[arg], "r"); 
     if (!in) { 
      fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno)); 
      return EXIT_FAILURE; 
     } 

     printf("%s unsigned char %s[] %s= {", storage, varname, attributes); 

     bytes = 0; 
     while ((ch = getc(in)) != EOF) 
      if (bytes++ % columns) 
       printf(", %3u", (unsigned int)ch); 
      else 
       printf("\n%s%3u", indent, (unsigned int)ch); 

     printf("\n}; /* %zu bytes */\n\n", bytes); 

     if (ferror(in)) { 
      fclose(in); 
      fprintf(stderr, "%s: Read error.\n", argv[arg]); 
      return EXIT_FAILURE; 
     } 
     if (fclose(in)) { 
      fprintf(stderr, "%s: Delayed read error.\n", argv[arg]); 
      return EXIT_FAILURE; 
     } 

     if (fflush(stdout) || ferror(stdout)) { 
      fprintf(stderr, "Error writing to standard output.\n"); 
      return EXIT_FAILURE; 
     } 

     arg++; 
    } 

    return EXIT_SUCCESS; 
} 

のみPOSIX-ISMはsize_tをスキャンして印刷する%zuの使用です。

関連する問題