GNU/Linux >> Znalost Linux >  >> Linux

C/C++ s GCC:Statické přidávání zdrojových souborů do spustitelného souboru/knihovny

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é:

  1. Dostanete text ven, takže to může být ve správě verzí a rozumné opravy
  2. 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 ldgcc 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.


Linux
  1. Najděte soubory a adresáře v Linuxu pomocí příkazu find

  2. Jak přidat čísla řádků do textových souborů v systému Linux

  3. Odeslání a příjem souboru v programování soketu v Linuxu s C/C++ (GCC/G++)

  1. (C/C++) Jak vygenerovat spustitelný soubor, který lze spustit na Windows i Linuxu?

  2. Propojení sdílené knihovny s jinou sdílenou knihovnou v linuxu

  3. Soubory ZIP se v Linuxu rozšiřují zpětnými lomítky, žádné podadresáře

  1. Když spustitelné soubory nejsou?

  2. Nahrajte soubory jako ASCII nebo binární pomocí FTP

  3. Jak na to:Programování v C s dočasnými soubory v Linuxu