2016-03-19 3 views
0

Я изучаю, как создавать библиотеки только с терминалом. Возможно ли (и, как я подозреваю, это не так) разместить ресурсы, такие как изображения, текст, API-ключи и т. Д., В статически связанный файл архива, например, в NSBundle? Как я могу ссылаться на эти ресурсы?Вставить ресурс в Static Library - C/C++

+0

Это не стандартная функция компоновщика, и для этого нет стандартного метода. Однако есть несколько ссылок, которые поддерживают внедрение статических ресурсов, даже в библиотеки. Поскольку вы не указали ОС и среду разработки, ответить на ваш вопрос невозможно. – tofro

+0

@tofro Любая ОС, которую я буду использовать, будет POSIX, но я надеялся на что-то портативное, если это возможно. Есть ли ссылки, которые вы могли бы порекомендовать? –

+0

Если вы ищете что-то * действительно * портативное: напишите свой собственный конвертер, который создает код C из ваших двоичных данных, таких как * const unsigned char blob [] = {0x0,022, .....} *. Затем выполните компиляцию и ссылку. не должно быть слишком сложно. Все остальное не переносится. – tofro

ответ

0

Что вы хотите сделать, это создать объектный файл из двоичного блоба, чтобы иметь возможность ссылаться на него. Это нуждается в, чтобы быть объектным файлом, который содержит таблицу символов с хотя бы одним символом (возможно, начало вашего блоба), потому что вы хотите иметь дескриптор ваших двоичных данных в остальной части программы.

Поскольку объектные файлы полностью зависят от системы (иногда даже от компилятора), нет никакого портативного способа фактически сделать это напрямую. Например, Linux довольно долгое время имел как минимум два разных формата объектных файлов.

Самый портативный (и, возможно, даже самый простой) способ сделать это: Используйте инструмент, который знает, как создавать объектные файлы для окружающей среды Dev: компилятор Си.

Написать свой собственный конвертер, который создает код C из ваших двоичных данных как

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

Затем скомпилировать и ссылки. не должно быть слишком сложно, а 10-минутная работа. Все остальное совершенно не переносится.

На платформах, где у вас есть GNU objcopy, это может быть другим способом делать вещи. (Укажите «двоичный» формат входного файла и формат объектного файла в качестве выходной цели. Вам также нужно использовать «-add-symbol», чтобы добавить этот символ начала вашего блоба.) Но я никогда не делал этого сам.

0

В системах POSIX, у вас есть довольно много стандартной оболочки sh, четыре очень полезные утилит оболочки под названием rm, printf, od и sed.

Допустим, вы хотите создать файл foo.c с const unsigned char blob[] массив, содержащий содержимое двоичного файла foo.bar:

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. Это гарантирует, что утилиты используют формат, который мы ожидаем, вместо некоторого локализованного варианта.

Вторая линия удаляет возможно существующие foo.c. (Некоторые оболочки жалуются, если вы направляете вывод в существующий файл, не добавляя его.) -f удовлетворяет любые жалобы, если файл еще не существует.

Третья и пятая строки добавляют определение массива и закрываются до файла foo.c.

В четвертой строке используется утилита od для вывода содержимого foo.bar в виде шестнадцатеричных байтов. Мы используем sed для добавления 0x и добавляем U, к каждому шестнадцатеричному байту, чтобы сделать его симпатичным и симпатичным C, а затем добавим еще три пробела к строке (делая ее отступом четырьмя пробелами).

Если вам не нравится этот подход, вы всегда можете написать свою собственную утилиту, чтобы сделать именно это.Например: #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-изма в приведенном выше коде является использование %zu для сканирования и печати size_t.

Смежные вопросы