简体   繁体   中英

Embed data in a C++ program

I've got a C++ program that uses SQLite. I want to store the SQL queries in a separate file -- a plain-text file, not a source code file -- but embed that file in the executable file like a resource.

(This has to run on Linux, so I can't store it as an actual resource as far as I know, though that would be perfect if it were for Windows.)

Is there any simple way to do it, or will it effectively require me to write my own resource system for Linux? (Easily possible, but it would take a lot longer.)

You can use objcopy to bind the contents of the file to a symbol your program can use. See, for instance, here for more information.

Use macros. Technically that file would be source code file but it wouldn't look like this. Example:

//queries.incl - SQL queries
Q(SELECT * FROM Users)
Q(INSERT [a] INTO Accounts)


//source.cpp
#define Q(query) #query,
char * queries[] = {
#include "queries.incl"
};
#undef Q

Later on you could do all sorts of other processing on that file by the same file, say you'd want to have array and a hash map of them, you could redefine Q to do another job and be done with it.

您始终可以编写一个小程序或脚本,将文本文件转换为头文件,并将其作为构建过程的一部分运行。

Here's a sample that we used for cross-platform embeddeding of files. It's pretty simplistic, but will probably work for you.

You may also need to change how it's handling linefeeds in the escapeLine function.

#include <string>
#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

std::string escapeLine( std::string orig )
{
    string retme;
    for (unsigned int i=0; i<orig.size(); i++)
    {
        switch (orig[i])
        {
        case '\\':
            retme += "\\\\";
            break;
        case '"':
            retme += "\\\"";
            break;
        case '\n': // Strip out the final linefeed.
            break;
        default:
            retme += orig[i];
        }
    }
    retme += "\\n"; // Add an escaped linefeed to the escaped string.
    return retme;
}

int main( int argc, char ** argv )
{
    string filenamein, filenameout;

    if ( argc > 1 )
        filenamein = argv[ 1 ];
    else
    {
        // Not enough arguments
        fprintf( stderr, "Usage: %s <file to convert.mel> [ <output file name.mel> ]\n", argv[0] );
        exit( -1 );
    }

    if ( argc > 2 )
        filenameout = argv[ 2 ];
    else
    {
        string new_ending = "_mel.h";
        filenameout = filenamein;
        std::string::size_type pos;
        pos = filenameout.find( ".mel" );
        if (pos == std::string::npos)
            filenameout += new_ending;
        else
            filenameout.replace( pos, new_ending.size(), new_ending );
    }

    printf( "Converting \"%s\" to \"%s\"\n", filenamein.c_str(), filenameout.c_str() );

    ifstream filein( filenamein.c_str(), ios::in );
    ofstream fileout( filenameout.c_str(), ios::out );

    if (!filein.good())
    {
        fprintf( stderr, "Unable to open input file %s\n", filenamein.c_str() );
        exit( -2 );
    }
    if (!fileout.good())
    {
        fprintf( stderr, "Unable to open output file %s\n", filenameout.c_str() );
        exit( -3 );
    }

    // Write the file.
    fileout << "tempstr = ";

    while( filein.good() )
    {
        string buff;
        if ( getline( filein, buff ) )
        {
            fileout << "\"" << escapeLine( buff ) << "\"" << endl;
        }
    }

    fileout << ";" << endl;

    filein.close();
    fileout.close();

    return 0;
}

It's slightly ugly, but you can always use something like:

const char *query_foo =
#include "query_foo.txt"

const char *query_bar =
#include "query_bar.txt"

Where query_foo.txt would contain the quoted query text.

I have seen this to be done by converting the resource file to a C source file with only one char array defined containing the content of resource file in a hexadecimal format (to avoid problems with malicious characters). This automatically generated source file is then simply compiled and linked to the project.

It should be pretty easy to implement the convertor to dump C file for each resource file also as to write some facade functions for accessing the resources.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM