Is there a way to load a binary file as a const variable in C at compile time
Asked Answered
D

3

10

I was wondering if there is a way to load an external binary file as a variable in C through an include or a header file or something of the like.

For example, in a project I am currently working on I am working with an embedded system that has a graphic display that will do text and minor graphics (boxes, lines, etc.) using ASCII data and commands. But, it will also display monochrome bitmaps. So I have a series of static displays that I use for a user interface, and a couple of bitmaps for splash screens.

Now the reason I mention that it is an embedded system is that there is no file system to load data from, only RAM and program memory, so any "pre-fab" data or tables I wish to use must but loaded at compile time either through a source file or through an object file using the linker. Unfortunately, the IDE does not provide any means to load a binary, in any form really, into program memory for use as a data cache in this fashion in any readily recognizable fashion.

So short of doing what I already have to get around this, (use a hex editor to read the binary as ASCII encoded hex and copy and paste the raw data into a header file as a variable), is there a way to "link" to a file or "include" a file that could be loaded as a const variable at compile time?

The system I am working with is MPLAB X for the Microchip series of processors and the compiler is GNC. I am mainly looking to know if there is a way to do this through some C command or function before I go trying to look for a way specifically through their specific compiler/linker software.

Dialyser answered 17/3, 2014 at 13:14 Comment(3)
Try xxd -iThe
GCC doesn't provide this feature but most assemblers, including GAS, do provide an ".incbin" directive for this purpose. This is usually more convenient to integrate into your typical IDE build systems compared to separate converters to C data or object filesSappington
The method I have used enables screen/logo/data changes after the compile (at the programmer) and stores it in program space. I used it for calibration coefficients going from unity to calculated and was reliable. If your interested, I'll make an answer, but another day.Bellerophon
D
5

No you can't do this directly. One way is to convert your binary files into C source code and include these pieces into your project. The conversion can be done by a simple program written by you or by some third party program.

For example:

Binaray1.c (generated automatically)

unsigned char binaray_file1[] =
{
  1,2,3,10,20,
  ....
} ;

Binaray2.c (generated automatically)

unsigned char binaray_file2[] =
{
  0,0,10,20,45,32,212,
  ....
} ;

SomeSourceFile.c

extern unsigned char binary_file1[] ;
extern unsigned char binary_file2[] ;

// use binary_file1 and binary_file2 here.
Donau answered 17/3, 2014 at 13:50 Comment(1)
Thanks for the heads up. This is exactly what I had already done, though I did it manually using a hex editor and the compiler IDE.Dialyser
C
5

The usual way to do this on Unix-like systems is using ld -r binary. Here's a tutorial for Linux: http://www.burtonini.com/blog/computers/ld-blobs-2007-07-13-15-50

In summary, the command:

ld -r -b binary -o foo.o foo.txt

will produce an object file foo.o that contains the symbols _binary_foo_txt_start, _binary_foo_txt_size, and _binary_foo_txt_end, which can be used like:

extern char _binary_foo_txt_start[];

And one for Mac OS X, which is a little more complex: Compile a binary file for linking OSX

The idea is to have the linker create an object file with known symbol names which point to the beginning and end of a binary blob which it copies into the resulting object file. You then link that object file into your application, and reference the blob via extern char* pointers or so.

I suppose you know how to link objects on your system, so the remaining question is whether your linker supports something like -r binary.

Clouse answered 17/3, 2014 at 13:20 Comment(2)
Actually that was the next step of this if C didn't provide for it natively through source files. For this though, I'm going to head over to the Microchip forums and ask around there to see if anyone has done something like this. Since the Microchip compiler and linker is specifically for their embedded systems not for any operating system and is only "based" on GNC I figure it wouldn't be appropriate to be delving into linker scripts and command line options here.Dialyser
To expand on this answer (esp. since the linked article is now a 404); for GNU ld, the command ld -r -b binary -o foo.o foo.txt will produce an object file foo.o that contains the symbols _binary_foo_txt_start, _binary_foo_txt_size, and _binary_foo_txt_end, that can be used like extern char _binary_foo_txt_start[];.Qualmish
D
5

No you can't do this directly. One way is to convert your binary files into C source code and include these pieces into your project. The conversion can be done by a simple program written by you or by some third party program.

For example:

Binaray1.c (generated automatically)

unsigned char binaray_file1[] =
{
  1,2,3,10,20,
  ....
} ;

Binaray2.c (generated automatically)

unsigned char binaray_file2[] =
{
  0,0,10,20,45,32,212,
  ....
} ;

SomeSourceFile.c

extern unsigned char binary_file1[] ;
extern unsigned char binary_file2[] ;

// use binary_file1 and binary_file2 here.
Donau answered 17/3, 2014 at 13:50 Comment(1)
Thanks for the heads up. This is exactly what I had already done, though I did it manually using a hex editor and the compiler IDE.Dialyser
M
0

Of course you could invent your own format, but before you do so: have a look into the XPM bitmap format which is exactly meant for that purpose: integrating pixmaps into C source code.

Meyers answered 17/3, 2014 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.