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.