Встраивать данные в программу на C ++ - PullRequest
17 голосов
/ 16 сентября 2008

У меня есть программа на C ++, которая использует SQLite. Я хочу хранить запросы SQL в отдельном файле - текстовом файле, , а не файле исходного кода, - но внедрить этот файл в исполняемый файл как ресурс.

(Это должно работать в Linux, поэтому я не могу хранить его как реальный ресурс, насколько мне известно, хотя это было бы идеально, если бы это было для Windows.)

Есть ли какой-нибудь простой способ сделать это, или это фактически потребует от меня написания моей собственной системы ресурсов для Linux? (Легко возможно, но это займет намного больше времени.)

Ответы [ 6 ]

24 голосов
/ 16 сентября 2008

Вы можете использовать objcopy для привязки содержимого файла к символу, который может использовать ваша программа. См., Например, здесь для получения дополнительной информации.

3 голосов
/ 16 сентября 2008

Вы всегда можете написать небольшую программу или скрипт, чтобы преобразовать ваш текстовый файл в файл заголовка и запустить его как часть процесса сборки.

3 голосов
/ 16 сентября 2008

Использовать макросы. Технически этот файл будет исходный код файл, но он не будет выглядеть так. Пример:

//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

Позже вы можете выполнять все другие виды обработки этого файла в том же файле, скажем, вы хотите иметь массив и их хэш-карту, вы можете переопределить Q, чтобы выполнить другую работу и выполнить ее.

2 голосов
/ 16 сентября 2008

Вот пример, который мы использовали для кросс-платформенного встраивания файлов. Это довольно упрощенно, но, вероятно, будет работать для вас.

Вам также может понадобиться изменить способ обработки перевода строки в функции escapeLine.

#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;
}
1 голос
/ 16 сентября 2008

Это немного уродливо, но вы всегда можете использовать что-то вроде:

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

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

Где query_foo.txt будет содержать цитируемый текст запроса.

0 голосов
/ 16 сентября 2008

Я видел, что это было сделано путем преобразования файла ресурсов в исходный файл C, в котором определен только один массив символов, содержащий содержимое файла ресурсов в шестнадцатеричном формате (чтобы избежать проблем с вредоносными символами). Этот автоматически сгенерированный исходный файл затем просто компилируется и связывается с проектом.

Должно быть довольно легко реализовать конвертер для выгрузки файла C для каждого файла ресурсов, а также для написания некоторых фасадных функций для доступа к ресурсам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...