GNU/Linux >> Linux Esercitazione >  >> Linux

C/C++ con GCC:aggiunta statica di file di risorse all'eseguibile/libreria

Con imagemagick:

convert file.png data.h

Restituisce qualcosa come:

/*
  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, 

....

Per compatibilità con altro codice puoi quindi utilizzare fmemopen per ottenere un FILE * "normale". oggetto, o in alternativa std::stringstream per creare un iostream . std::stringstream non è eccezionale per questo però e ovviamente puoi semplicemente usare un puntatore ovunque tu possa usare un iteratore.

Se lo stai usando con automake, non dimenticare di impostare BUILT_SOURCES in modo appropriato.

La cosa bella di farlo in questo modo è:

  1. Ottieni il testo, quindi può essere nel controllo della versione e patch in modo ragionevole
  2. È portatile e ben definito su ogni piattaforma

Puoi incorporare file binari nell'eseguibile usando ld linker. Ad esempio, se hai il file foo.bar quindi puoi incorporarlo nell'eseguibile aggiungendo i seguenti comandi a ld

--format=binary foo.bar --format=default

Se stai invocando ld attraverso gcc quindi dovrai aggiungere -Wl

-Wl,--format=binary -Wl,foo.bar -Wl,--format=default

Qui --format=binary dice al linker che il seguente file è binario e --format=default ritorna al formato di input predefinito (questo è utile se specifichi altri file di input dopo foo.bar ).

Quindi puoi accedere al contenuto del tuo file dal codice:

extern uint8_t data[]     asm("_binary_foo_bar_start");
extern uint8_t data_end[] asm("_binary_foo_bar_end");

C'è anche un simbolo chiamato "_binary_foo_bar_size" . Penso che sia di tipo uintptr_t ma non l'ho controllato.


Aggiorna Ho imparato a preferire il controllo dell'assembly .incbin di John Ripley offerte di soluzioni basate e ora utilizza una variante su questo.

Ho usato objcopy (GNU binutils) per collegare i dati binari da un file foo-data.bin nella sezione dati dell'eseguibile:

objcopy -B i386 -I binary -O elf32-i386 foo-data.bin foo-data.o

Questo ti dà un foo-data.o oggetto che puoi collegare al tuo eseguibile. L'interfaccia C è simile a

/** 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");

quindi puoi fare cose come

for (uint8_t *byte=foo_data; byte<foo_data_end; ++byte) {
    transmit_single_byte(*byte);
}

o

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);

Se la tua architettura di destinazione ha vincoli speciali su dove vengono archiviati i dati costanti e variabili o desideri archiviare tali dati nel .text segmento per farlo rientrare nello stesso tipo di memoria del codice del programma, puoi giocare con il objcopy altri parametri.


Linux
  1. Quando i file eseguibili non lo sono?

  2. Invia e ricevi un file nella programmazione socket in Linux con C/C++ (GCC/G++)

  3. Itera su un elenco di file con spazi

  4. Come aggiungere il file .so a java.library.path in Linux

  5. Clang può compilare codice con le librerie .a compilate da GCC?

Linux:come condividere file su una rete locale con woof

Suggerimenti Vim:modifica file remoti con Vim su Linux

Trova i file persi con Scalpel

Come copiare file con estensione di file specifica in modo ricorsivo

Un modo semplice per unire i file con il comando Cat

Collegamento di una libreria condivisa con un'altra libreria condivisa in Linux