Avec imagemagick :
convert file.png data.h
Donne quelque chose comme :
/*
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,
....
Pour la compatibilité avec d'autres codes, vous pouvez alors utiliser soit fmemopen
pour obtenir un FILE *
"normal" objet, ou alternativement std::stringstream
faire un iostream
. std::stringstream
n'est pas idéal pour cela cependant et vous pouvez bien sûr simplement utiliser un pointeur partout où vous pouvez utiliser un itérateur.
Si vous l'utilisez avec automake, n'oubliez pas de définir BUILT_SOURCES de manière appropriée.
La bonne chose à faire de cette façon est :
- Vous obtenez du texte, de sorte qu'il peut être dans le contrôle de version et les correctifs judicieusement
- Il est portable et bien défini sur chaque plate-forme
Vous pouvez intégrer des fichiers binaires dans un exécutable en utilisant ld
linker.Par exemple, si vous avez le fichier foo.bar
alors vous pouvez l'intégrer dans un exécutable en ajoutant les commandes suivantes à ld
--format=binary foo.bar --format=default
Si vous appelez ld
jusqu'à gcc
alors vous devrez ajouter -Wl
-Wl,--format=binary -Wl,foo.bar -Wl,--format=default
Ici --format=binary
indique à l'éditeur de liens que le fichier suivant est binaire et --format=default
revient au format d'entrée par défaut (ceci est utile si vous spécifiez d'autres fichiers d'entrée après foo.bar
).
Ensuite, vous pouvez accéder au contenu de votre fichier à partir du code :
extern uint8_t data[] asm("_binary_foo_bar_start");
extern uint8_t data_end[] asm("_binary_foo_bar_end");
Il existe également un symbole nommé "_binary_foo_bar_size"
. Je pense qu'il est de type uintptr_t
mais je n'ai pas vérifié.
Mettre à jour J'ai appris à préférer le contrôle de l'assemblage de John Ripley .incbin
offres de solutions basées sur des offres et maintenant utiliser une variante sur cela.
J'ai utilisé objcopy (GNU binutils) pour lier les données binaires d'un fichier foo-data.bin dans la section data de l'exécutable :
objcopy -B i386 -I binary -O elf32-i386 foo-data.bin foo-data.o
Cela vous donne un foo-data.o
fichier objet que vous pouvez lier dans votre exécutable. L'interface C ressemble à quelque chose comme
/** 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");
pour que vous puissiez faire des choses comme
for (uint8_t *byte=foo_data; byte<foo_data_end; ++byte) {
transmit_single_byte(*byte);
}
ou
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);
Si votre architecture cible a des contraintes particulières quant à l'endroit où les données constantes et variables sont stockées, ou si vous souhaitez stocker ces données dans le .text
segment pour le faire tenir dans le même type de mémoire que votre code de programme, vous pouvez jouer avec le objcopy
paramètres un peu plus.