Mit imagemagick:
convert file.png data.h
Ergibt etwas wie:
/*
data.h (PNM).
*/
static unsigned char
MagickImage[] =
{
0x50, 0x36, 0x0A, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4D, 0x50, 0x0A, 0x32, 0x37,
0x37, 0x20, 0x31, 0x36, 0x32, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
....
Für die Kompatibilität mit anderem Code können Sie dann entweder fmemopen verwenden um eine "normale" FILE * zu erhalten Objekt oder alternativ std::stringstream um eine iostream zu machen . std::stringstream ist dafür aber nicht gut und Sie können natürlich überall dort, wo Sie einen Iterator verwenden können, einfach einen Zeiger verwenden.
Wenn Sie dies mit automake verwenden, vergessen Sie nicht, BUILT_SOURCES entsprechend einzustellen.
Das Schöne daran, es so zu machen, ist:
- Sie bekommen Text raus, damit er in der Versionskontrolle und Patches sinnvoll sein kann
- Es ist portabel und auf jeder Plattform gut definiert
Mit ld können Sie Binärdateien in ausführbare Dateien einbetten Linker. Zum Beispiel, wenn Sie die Datei foo.bar haben dann können Sie es in eine ausführbare Datei einbetten, indem Sie die folgenden Befehle zu ld hinzufügen
--format=binary foo.bar --format=default
Wenn Sie ld aufrufen bis gcc dann müssen Sie -Wl hinzufügen
-Wl,--format=binary -Wl,foo.bar -Wl,--format=default
Hier --format=binary teilt dem Linker mit, dass die folgende Datei binär ist und --format=default schaltet zurück zum Standard-Eingabeformat (dies ist nützlich, wenn Sie nach foo.bar andere Eingabedateien angeben ).
Dann können Sie mit folgendem Code auf den Inhalt Ihrer Datei zugreifen:
extern uint8_t data[] asm("_binary_foo_bar_start");
extern uint8_t data_end[] asm("_binary_foo_bar_end");
Es gibt auch ein Symbol namens "_binary_foo_bar_size" . Ich denke, es ist vom Typ uintptr_t aber ich habe es nicht überprüft.
Aktualisieren Ich bevorzuge inzwischen die Steuerung von John Ripleys Assembly .incbin basierende Lösungsangebote und nutzen Sie nun eine Variante davon.
Ich habe objcopy (GNU binutils) verwendet, um die Binärdaten aus einer Datei foo-data.bin in den Datenabschnitt der ausführbaren Datei zu verlinken:
objcopy -B i386 -I binary -O elf32-i386 foo-data.bin foo-data.o
Dies gibt Ihnen einen foo-data.o Objektdatei, die Sie in Ihre ausführbare Datei einbinden können. Die C-Schnittstelle sieht in etwa so aus
/** created from binary via objcopy */
extern uint8_t foo_data[] asm("_binary_foo_data_bin_start");
extern uint8_t foo_data_size[] asm("_binary_foo_data_bin_size");
extern uint8_t foo_data_end[] asm("_binary_foo_data_bin_end");
damit Sie Dinge tun können wie
for (uint8_t *byte=foo_data; byte<foo_data_end; ++byte) {
transmit_single_byte(*byte);
}
oder
size_t foo_size = (size_t)((void *)foo_data_size);
void *foo_copy = malloc(foo_size);
assert(foo_copy);
memcpy(foo_copy, foo_data, foo_size);
Wenn Ihre Zielarchitektur spezielle Einschränkungen hinsichtlich des Speicherorts konstanter und variabler Daten hat oder Sie diese Daten in .text speichern möchten Segment, damit es in denselben Speichertyp wie Ihr Programmcode passt, können Sie mit dem objcopy spielen Parameter etwas mehr.