Con imagemagick:
convert file.png data.h
Da algo como:
/*
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,
....
Para compatibilidad con otro código, puede usar fmemopen
para obtener un FILE *
"regular" objeto, o alternativamente std::stringstream
para hacer un iostream
. std::stringstream
Sin embargo, no es bueno para esto y, por supuesto, puede usar un puntero en cualquier lugar donde pueda usar un iterador.
Si está utilizando esto con automake, no olvide configurar BUILT_SOURCES de manera adecuada.
Lo bueno de hacerlo de esta manera es:
- Obtienes el texto, por lo que puede estar en el control de versiones y parches con sensatez
- Es portátil y está bien definido en todas las plataformas
Puede incrustar archivos binarios en el ejecutable usando ld
enlazador. Por ejemplo, si tiene el archivo foo.bar
luego puede incrustarlo en el ejecutable agregando los siguientes comandos a ld
--format=binary foo.bar --format=default
Si está invocando ld
hasta gcc
entonces deberá agregar -Wl
-Wl,--format=binary -Wl,foo.bar -Wl,--format=default
Aquí --format=binary
le dice al enlazador que el siguiente archivo es binario y --format=default
vuelve al formato de entrada predeterminado (esto es útil si va a especificar otros archivos de entrada después de foo.bar
).
Luego puede acceder al contenido de su archivo desde el código:
extern uint8_t data[] asm("_binary_foo_bar_start");
extern uint8_t data_end[] asm("_binary_foo_bar_end");
También hay un símbolo llamado "_binary_foo_bar_size"
. Creo que es del tipo uintptr_t
pero no lo comprobé.
Actualizar He llegado a preferir el montaje de control de John Ripley .incbin
ofertas de soluciones basadas y ahora use una variante de eso.
He usado objcopy (GNU binutils) para vincular los datos binarios de un archivo foo-data.bin a la sección de datos del ejecutable:
objcopy -B i386 -I binary -O elf32-i386 foo-data.bin foo-data.o
Esto te da un foo-data.o
archivo de objeto que puede vincular a su ejecutable. La interfaz C se parece 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");
para que puedas hacer cosas como
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);
Si su arquitectura de destino tiene restricciones especiales en cuanto a dónde se almacenan los datos constantes y variables, o si desea almacenar esos datos en el .text
segmento para que encaje en el mismo tipo de memoria que el código de su programa, puede jugar con el objcopy
parámetros un poco más.