Как вставить файл в исполняемый файл?
У меня есть небольшой демонстрационный исполняемый файл, написанный на С++, который зависит только от одного загружаемого PNG-изображения размером 5 килобайт до его запуска, который используется для текста пикселя, который я сделал. Из-за этого одного файла мне нужно будет выдать ZIP-архив, а не только один исполняемый файл, что создает достаточное трение между загрузкой и "игрой", которые, как я считаю, будут отговаривать некоторых из них.
Мой вопрос в том, есть ли в любом случае встроить PNG файл (и любой другой файл) в исполняемый или исходный код, чтобы он был единственным файлом, и исполняемый файл может его использовать?
У меня есть возможность анализировать PNG как поток байтов, поэтому он не нуждается в преобразовании в данные пикселя.
Спасибо заранее! (Другие вопросы с похожим названием для этого существуют, но они и их ответы, похоже, затрагивают более конкретные проблемы и не очень помогают)
edit. Компилятор - это Visual С++ 2010, и это работает в Windows (хотя я бы хотел, чтобы для этого были использованы специальные утилиты для Windows)
edit2: ответ Alf казался самым переносимым методом, поэтому я быстро написал функцию для синтаксического анализа PNG файла в TXT или заголовочный файл, который можно было бы читать как массив unsigned char
. Кажется, что он идентичен в этом виде самому файлу PNG, но мой загрузчик png не принимает массив. При загрузке из памяти парсер PNG принимает (void * buffer, size_t length)
, если это имеет значение.
Код, если вы хотите его увидеть, но я по-прежнему буду принимать другие ответы, если вы думаете, что они лучше этого метода:
void compileImagePNGtoBinary(char * filename, char * output){
FILE * file = fopen(filename, "rb");
FILE * out = fopen(output, "w");
unsigned char buffer[32];
size_t count;
fprintf(out, "#pragma once \n\n static unsigned char TEXT_PNG_BYTES[] = { ");
while(!feof(file)){
count = fread(buffer, 1, 32, file);
for(int n = 0; n < count; ++n){
fprintf(out, "0x%02X, ", buffer[n]);
};
};
fprintf(out, "};");
fclose(file);
fclose(out);
};
Final Edit: ImageMagick, о котором Alf также упомянул, именно то, что мне нужно, спасибо!
Ответы
Ответ 1
Портативный способ - определить функцию типа
typedef unsigned char Byte;
Byte const* pngFileData()
{
static Byte const data =
{
// Byte data generated by a helper program.
};
return data;
}
Тогда вам нужно только написать небольшую вспомогательную программу, которая читает PNG файл как двоичный файл и генерирует текст инициализатора фигурных скобок С++. Изменить: @awoodland указала в комментарии к вопросу, что ImageMagick имеет такую небольшую вспомогательную программу & hellip;
Конечно, для программы, зависящей от Windows, вместо этого используйте обычную схему ресурсов Windows.
Приветствия и hth.,
Ответ 2
Посмотрите на XD:
http://www.fourmilab.ch/xd/
Наконец, xd может читать двоичный файл и испускать данные языка C которое содержит данные из файла. Это удобно, когда вы хотите встроить двоичные данные в программы C.
Лично я использую ресурсы для окон, но если вам нужен действительно переносимый способ, который не включает знание исполняемого формата, это путь. PNG, JPG, что угодно...
Ответ 3
Это зависит от исполняемого файла, что означает зависящую от операционной системы/компилятора. Windows предлагает систему ресурсов для этого, как указано в этом вопросе.
Ответ 4
Base64 закодировать файл и поместить его в строку где-нибудь в вашем коде;)
Ответ 5
Вы можете вставлять любые произвольные файлы в свои программные ресурсы: (MSDN) Пользовательский ресурс.
Определяемый пользователем оператор определения ресурса определяет ресурс, содержащий данные, относящиеся к конкретным приложениям. Данные могут иметь любой формат и могут быть определены либо как содержимое данного файла (если указан параметр имени файла), либо как серия чисел и строк (если указан блок необработанных данных).
nameID typeID filename
Имя файла указывает имя файла, содержащего двоичные данные ресурса. Содержимое файла включено в качестве ресурса. RC не интерпретирует двоичные данные каким-либо образом. Обязанности программиста - обеспечить правильное выравнивание данных для целевой компьютерной архитектуры.
После этого вы можете использовать функцию LoadResource для доступа к байтам, содержащимся в файле.
Ответ 6
В linux я использую это. Это основано на нескольких примерах, которые я обнаружил при попытке сделать несколько демонстраций 4k, хотя и немного изменился. Я считаю, что он может работать и с окнами, но не с встроенной сборкой VS по умолчанию. Мое обходное решение #defining макроса для использования этого кода или системы ресурсов Windows, что @MarkRansom предлагает (довольно больно работать, но в конечном итоге работает).
//USAGE: call BINDATA(name, file.txt) and access the char array &name.
#ifndef EMBED_DATA_H
#define EMBED_DATA_H
#ifdef _WIN32
//#error The VS ASM compiler won't work with this, but you can get external ones to do the trick
#define BINDATA #error BINDATA requires nasm
#else
__asm__(
".altmacro\n" \
".macro binfile p q\n" \
" .global \\p\n" \
"\\p:\n" \
" .incbin \\q\n" \
"\\p&_end:\n" \
" .byte 0\n" \
" .global \\p&_len\n" \
"\\p&_len:\n" \
" .int(\\p&_end - \\p)\n" \
".endm\n\t"
);
#ifdef __cplusplus
extern "C" {
#endif
#define BINDATA(n, s) \
__asm__("\n\n.data\n\tbinfile " #n " \"" #s "\"\n"); \
extern char n; \
extern int n##_len;
#ifdef __cplusplus
}
#endif
#endif
#endif