Reputation: 176
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.
Upvotes: 10
Views: 6200
Reputation: 2371
With C23, you have the option of using the #embed
preprocessor directive.
With it, you can write something like this:
#include <stdio.h>
constexpr unsigned char graphdata[] = {
#embed "somefile.bin" if_empty("somefile.bin is empty")
};
int main()
{
if(sizeof graphdata == 22)
puts(graphdata); // Prints "somefile.bin is empty\n"
else
printf("graphdata is `%s'\n", graphdata);
}
This will compile if the preprocessor can find the "somefile.bin" file during compilation. I've also included a directive to detect if the file is empty, which provides some fallback content in that case.
If the file is not found at all, you get a compile error to that effect.
Upvotes: 3
Reputation: 249093
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
.
Upvotes: 5
Reputation: 3335
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.
Upvotes: 0
Reputation: 50768
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.
Upvotes: 5