Dengan imagemagick:
convert file.png data.h
Memberikan sesuatu seperti:
/*
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,
....
Untuk kompatibilitas dengan kode lain, Anda dapat menggunakan fmemopen
untuk mendapatkan FILE *
"biasa". objek, atau sebagai alternatif std::stringstream
untuk membuat iostream
. std::stringstream
tidak bagus untuk ini dan tentu saja Anda bisa menggunakan pointer di mana pun Anda bisa menggunakan iterator.
Jika Anda menggunakan ini dengan automake, jangan lupa untuk menyetel BUILT_SOURCES dengan benar.
Hal yang menyenangkan tentang melakukannya dengan cara ini adalah:
- Anda mengeluarkan teks, sehingga dapat berada dalam kontrol versi dan tambalan dengan wajar
- Ini portabel dan terdefinisi dengan baik di setiap platform
Anda dapat menyematkan file biner dalam file yang dapat dieksekusi menggunakan ld
linker.Misalnya, jika Anda memiliki file foo.bar
maka Anda dapat menyematkannya dalam executable dengan menambahkan perintah berikut ke ld
--format=binary foo.bar --format=default
Jika Anda memanggil ld
melalui gcc
maka Anda perlu menambahkan -Wl
-Wl,--format=binary -Wl,foo.bar -Wl,--format=default
Ini --format=binary
memberi tahu linker bahwa file berikut adalah biner dan --format=default
beralih kembali ke format input default (ini berguna jika Anda akan menentukan file input lainnya setelah foo.bar
).
Kemudian Anda dapat mengakses konten file Anda dari kode:
extern uint8_t data[] asm("_binary_foo_bar_start");
extern uint8_t data_end[] asm("_binary_foo_bar_end");
Ada juga simbol bernama "_binary_foo_bar_size"
. Saya pikir ini adalah tipe uintptr_t
tapi saya tidak memeriksanya.
Perbarui Saya telah tumbuh untuk lebih memilih perakitan kontrol John Ripley .incbin
penawaran solusi berbasis dan sekarang gunakan varian untuk itu.
Saya telah menggunakan objcopy (GNU binutils) untuk menautkan data biner dari file foo-data.bin ke bagian data yang dapat dieksekusi:
objcopy -B i386 -I binary -O elf32-i386 foo-data.bin foo-data.o
Ini memberi Anda foo-data.o
file objek yang dapat Anda tautkan ke file yang dapat dieksekusi. Antarmuka C terlihat seperti
/** 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");
sehingga Anda dapat melakukan hal-hal seperti
for (uint8_t *byte=foo_data; byte<foo_data_end; ++byte) {
transmit_single_byte(*byte);
}
atau
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);
Jika arsitektur target Anda memiliki batasan khusus tentang tempat penyimpanan data konstan dan variabel, atau Anda ingin menyimpan data tersebut di .text
segmen agar sesuai dengan jenis memori yang sama dengan kode program Anda, Anda dapat bermain dengan objcopy
parameter lagi.