Embedding data in a C ++ program

I have a C ++ program that uses SQLite. I want to store SQL queries in a separate file - a text file, not a source code file, but insert this file into the executable file as a resource.

(This should be done on Linux, so I cannot store it as an actual resource, as far as I know, although it would be great if it were for Windows.)

Is there any easy way to do this, or will it require me to write my own resource system for Linux? (Easy, but it will take much longer.)

+17
c ++ linux sqlite
Sep 16 '08 at 14:03
source share
6 answers

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

+24
Sep 16 '08 at 14:17
source share

Use macros. Technically, this file will be the source code, but it will not 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 you can do all kinds of other processing in this file with the same file, say that you want to have an array and a hash map of them, you can override Q to do other work and do with it.

+3
Sep 16 '08 at 14:11
source share

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

+3
Sep 16 '08 at 14:12
source share

Here is an example that we used for cross-platform file embedding. This is pretty simplistic, but it will probably work for you.

You may also need to change the way lines are handled 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; } 
+2
Sep 16 '08 at 15:34
source share

This is a little 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 will contain the quoted text of the query.

+1
Sep 16 '08 at 14:12
source share

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

It is quite easy to implement a converter to output the C file for each resource file, also for writing some facade functions to access resources.

0
Sep 16 '08 at 14:15
source share



All Articles