ar2015
ar2015

Reputation: 6140

Redirect a raw C array data into a data file in embedded system industries

I have seen some codes that have no function. They just have data and the file is supposed to be converted to a data file not an executable.

For example, it is something like

config.c

const unsigned char configData[] = \
"Cnf"
"\0x01\0x01\0x00\0x00\0x00\0x00\0x00\0x00"
"LOCAL/ITEM.MSG\0x00"
"\x7E\xD1\xF5\x3A\0x00\0x00\0x00";

The file is supposed to turn into config.dat as binary starting with Cnf\0x01\0x01... and ending with \xF5\x3A\0x00\0x00\0x00 with no header or footer.

What is the name of such an action? I have problem for google keywords.

And, how can such an action be done using a gcc compiler?


Update: I am not after using fwrite or a library. I do not want to add anything to the above code or remove any line from it. Lets keep this file intact. My problem is not to create a binary file. My problem is mostly understanding how these particular files are handled by the compiler. I have seen such files in the embedded system industries. But not yet found how they work.

Upvotes: 0

Views: 118

Answers (1)

Joshua
Joshua

Reputation: 43278

Interpreting as: "How can I embed a binary file into my C program at build time?"

This is how I do it. I use a custom build step to convert the binary file to a .c file.

In Makefile:

program: main.c configData.c resource.h # and more
    $(CC) -o program main.c configData.c # and more

configData.c: configData.dat bin2c
    ./bin2c configData.dat configData.c

bin2c: bin2c.c
    $(HOSTCC) -o bin2c bin2c.c 

In resource.h:

extern char configData[];
extern size_t configDataLen;

In bin2c.c:

#include <stdio.h>
int main(int argc, char **argv)
{
    if (argc < 3) {
        fprintf(stderr, "Usage: bin2c binary.dat binary.c symbol\n");
        return 1;
    }
    FILE *in = fopen(argv[1], "rb");
    if (!in) { perror(argv[1]); return 1; }
    FILE *out = fopen(argv[2], "w");
    if (!out) { perror(argv[2]); return 1; }
    int c;
    long len = 0;
    fprintf(out, "#include <stddef.h>\n");
    fprintf(out, "char %s[] = {"
    while ((c = getc(in)) > EOF) {
        if (len > 0) puts(',', out);
        fprintf("%d", c);
        ++len;
        if (ferror(out)) { perror(argv[2]); return 1; }
    }
    fprintf(out, "};\n");
    fprintf(out, "size_t %sLen = %ld;", len);
    if (ferror(out)) { perror(argv[2]); return 1; }
    if (fclose(out)) { perror(argv[2]); return 1; } /* Yup check fclose for errors */
    if (ferror(in)) { perror(argv[1]); return 1; }
    return 0;
}

In .gitignore:

bin2c
configData.c

People have done better than this. I've seen fancy linker scripts that enable the linker to take dat files. My method has the advantage of being easy to understand and portable.

Upvotes: 1

Related Questions