Embed data in a C++ program

2020-01-31 02:08发布

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.)

标签: c++ linux sqlite
6条回答
何必那么认真
2楼-- · 2020-01-31 02:10

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.

查看更多
够拽才男人
3楼-- · 2020-01-31 02:10

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.

查看更多
聊天终结者
4楼-- · 2020-01-31 02:19

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.

查看更多
祖国的老花朵
5楼-- · 2020-01-31 02:21

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.

查看更多
别忘想泡老子
6楼-- · 2020-01-31 02:25

You can always write a small program or script to convert your text file into a header file and run it as part of your build process.

查看更多
【Aperson】
7楼-- · 2020-01-31 02:30

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;
}
查看更多
登录 后发表回答