S imagemagick:
convert file.png data.h
Dává něco jako:
/*
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,
....
Pro kompatibilitu s jiným kódem pak můžete použít buď fmemopen
získat "běžnou" FILE *
objekt nebo alternativně std::stringstream
vytvořit iostream
. std::stringstream
není pro to skvělé a samozřejmě můžete použít ukazatel kdekoli, kde můžete použít iterátor.
Pokud to používáte s automake, nezapomeňte vhodně nastavit BUILT_SOURCES.
Na tom, jak to udělat tímto způsobem, je hezké:
- Dostanete text ven, takže to může být ve správě verzí a rozumné opravy
- Je přenosný a dobře definovaný na každé platformě
Binární soubory můžete vložit do spustitelného souboru pomocí ld
linker. Například pokud máte soubor foo.bar
pak jej můžete vložit do spustitelného souboru přidáním následujících příkazů do ld
--format=binary foo.bar --format=default
Pokud vyvoláváte ld
až gcc
pak budete muset přidat -Wl
-Wl,--format=binary -Wl,foo.bar -Wl,--format=default
Zde --format=binary
sděluje linkeru, že následující soubor je binární a --format=default
přepne zpět na výchozí vstupní formát (toto je užitečné, pokud zadáte další vstupní soubory po foo.bar
).
Potom můžete přistupovat k obsahu svého souboru z kódu:
extern uint8_t data[] asm("_binary_foo_bar_start");
extern uint8_t data_end[] asm("_binary_foo_bar_end");
Existuje také symbol s názvem "_binary_foo_bar_size"
. Myslím, že je typu uintptr_t
ale nezkontroloval jsem to.
Aktualizovat Začal jsem preferovat řídicí sestavu Johna Ripleyho .incbin
založené řešení nabízí a nyní k tomu použijte variantu.
Použil jsem objcopy (GNU binutils) k propojení binárních dat ze souboru foo-data.bin do datové části spustitelného souboru:
objcopy -B i386 -I binary -O elf32-i386 foo-data.bin foo-data.o
Získáte tak foo-data.o
objektový soubor, který můžete propojit se svým spustitelným souborem. Rozhraní C vypadá nějak takto
/** 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");
takže můžete dělat věci jako
for (uint8_t *byte=foo_data; byte<foo_data_end; ++byte) {
transmit_single_byte(*byte);
}
nebo
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);
Pokud má vaše cílová architektura zvláštní omezení ohledně toho, kde jsou uložena konstantní a proměnná data, nebo chcete tato data uložit do .text
segment, aby se vešel do stejného typu paměti jako váš programový kód, můžete hrát s objcopy
další parametry.