Время оригинального вопроса может быть случайным. Оказывается, что в будущем подход Find/Load ресурса, который я предложил, не будет для нас ни возможностью (код, который я использовал ранее, идет межплатформенным), поэтому я придумал решение, которое также может работа для вас. Полный код - это немного, чтобы опубликовать его как ответ SO (но см. Мой комментарий), хотя вы, возможно, можете быстро приготовить свою собственную версию.
В принципе, я написал утилиту, которая просто принимает базовое имя для выходных файлов, как argv[1]
(« выходного BASENAME»), и argv[2...(argc-1)]
являются входными файлами. Я открываю output-base-name.cpp
и output-base-name.h
для записи (будет перезаписан, если они существуют).
Для каждого входного файла, утилита генератора делает это:
1: формирует переменное имя-дружественного идентификатор на основе имени файла (« generated_name»)
2: считывает входной файл
3: отвалы следующего в output-base-name.cpp
:
static uint8_t generated_name[] = {
// Initialize with contents of input file as a bunch of 0xNN, 0xNN... values.
};
и в output-base-name.h
, соответствующий
static const unsigned IDR_generated_name = N; // start at 0, see below re:range check
4: После последнего входного файла, заканчивает output-base-name.cpp
что-то вроде
static struct {
unsigned ID;
unsigned size; // I assume you aren't trying to embed files >4GB!
const uint8_t* data;
}
fileData[] = {
// one array element for each input file
{ IDR_generated_name, sizeof(generated_name), generated_name },
...
};
const uint8_t* getResourceData(unsigned ID){
// a real version would do a safer lookup/range check of some sort based on ID
return fileData[ID].data;
}
unsigned getResourceSize(unsigned ID){
// a real version would do a safer lookup/range check of some sort based on ID
return fileData[ID].size;
}
5: Завершает output-base-name.h
с прототипами для независимо от ваших "получить" функции выглядят как, например
extern const uint8_t* getResourceData(unsigned ID);
extern unsigned getResourceSize(unsigned ID);
Просто используйте output-base-name.h
везде, где вам нужно получить доступ к данным и добавить output-base-name.cpp
в свой Makefile или проект (сделать его зависимым от двоичных входных файлов, с помощью утилиты генератора в правиле сборки и make
автоматически восстанавливать его когда это необходимо). Если вы хотите, чтобы они были в динамической библиотеке какого-либо типа, просто добавьте соответствующие атрибуты экспорта в ваши функции «get».
Имейте генератор, завершающий вывод в пространстве имен, создавая для него класс-интерфейс, если вы хотите (или генерировать один вместо примера «получить»), и вы должны быть хорошими.
Этот подход имеет ряд преимуществ по сравнению с использованием несжатого архива (или даже встроенный ресурсный подход я предложил для целей Windows):
- Это намного проще иметь дело в коде приложения - нет чтения каталог zip, извлечение файлов и т. д.
- Нет дополнительной зависимости от другой сторонней библиотеки для поиска/извлечения данных файла (при условии, что вы не откатываете свою собственную zip-библиотеку, которая будет работать еще больше)
- Все действия по разрешению и поиску выполняются для вы - адреса для каждого байтового массива уже будут разрешены компоновщиком, если вставлять данные в статическую библиотеку или исполняемый файл или загрузчиком ОС, если общая библиотека или DLL
- Вы знаете, что данные будут существовать или ваш двоичный файл не может работать (не в случае с подходом zip lib или даже Find/LoadResource в Windows)
- Данные немного недоступны (поэтому безопаснее с) Joe User, по сравнению с zip-файлом
- Должно быть быстрее, чем почтовый или Windows-ресурс, из-за предварительного разрешения адресов данных во время процесса загрузки для приложения
- Он также может использоваться для любой формы относительно статических данных, которые вы хотите отправить (или сделать доступным) ваше приложение - просто файлы пакета в общую/динамическую библиотеку с генератором и использовать сгенерированные экспортированные функции доступа. Вы даже можете создавать обновленные или полностью новые пакеты данных позже (после компиляции/времени отправки) и загружать во время выполнения с помощью опций конфигурации.
- Он будет работать в старых компиляторов C++ при необходимости (или, без создания каких-либо пространства имен или класса обертки, даже набившие оскомину-C)
Это только пример подхода, который я использовал, но охватывает все основы, поэтому, если решение скорее, чем позже (опять же, см. комментарий) вам лучше, этого может быть достаточно (вы хотите, чтобы диапазон проверки значений в функциях «получить» - по крайней мере, в отладочных сборках , возможно, использовать какие-либо контейнеры вместо использования массива struct c-style и т. д.).
a) Zip не требует сжатия. b) Zip, 7z, Tar, Bzip2 и т. д. Существует много таких форматов. c) Вы всегда можете создать свой собственный формат двоичного файла. d) Помимо обычных архивных форматов, как упомянуто в b, есть также некоторые специализированные форматы файлов 3D-моделей (и libs для их сохранения/загрузки) ... – deviantfan
Что бы вы ни пошли, если вы будете загружать ресурсы по требованию, тогда вам нужен формат архива с индексом. Zip делает; смолы нет. Это означает, что с помощью tar вам придется искать повсюду, чтобы узнать, какие у вас есть ресурсы и где они находятся. – cdhowie
@cdhowie Основываясь на том, что все сказали, я думаю, что я собираюсь пойти с низким сжатым почтовым индексом. – BlueSpud