17

SQLite を使用する C++ プログラムがあります。SQLクエリを別のファイル(ソースコードファイルではなくプレーンテキストファイル)に保存したいのですが、そのファイルをリソースのように実行可能ファイルに埋め込みます。

(これは Linux で実行する必要があるため、私が知る限り、実際のリソースとして保存することはできませんが、Windows の場合は完璧です。)

それを行う簡単な方法はありますか、それとも Linux 用に独自のリソース システムを作成する必要がありますか? (簡単にできますが、もっと時間がかかります。)

4

6 に答える 6

25

objcopy を使用して、ファイルの内容をプログラムで使用できるシンボルにバインドできます。たとえば、詳細については、こちらを参照してください。

于 2008-09-16T14:17:44.077 に答える
4

マクロを使用します。技術的には、そのファイルはソースコードファイルになりますが、このようには見えません。例:

//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を再定義して別のジョブを実行し、それを実行できます。

于 2008-09-16T14:11:27.633 に答える
3

テキストファイルをヘッダーファイルに変換し、ビルドプロセスの一部として実行するために、いつでも小さなプログラムまたはスクリプトを作成できます。

于 2008-09-16T14:12:52.357 に答える
2

ファイルのクロスプラットフォーム埋め込みに使用したサンプルを次に示します。かなり単純ですが、おそらくうまくいくでしょう。

また、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;
}
于 2008-09-16T15:34:59.633 に答える
1

少し醜いですが、いつでも次のようなものを使用できます。

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

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

query_foo.txtには、引用符で囲まれたクエリテキストが含まれます。

于 2008-09-16T14:12:00.613 に答える
0

これは、リソース ファイルの内容を 16 進形式で含む char 配列が 1 つだけ定義された C ソース ファイルにリソース ファイルを変換することによって行われることがわかりました (悪意のある文字による問題を回避するため)。この自動生成されたソース ファイルは、コンパイルされてプロジェクトにリンクされるだけです。

各リソース ファイルの C ファイルをダンプするコンバーターを実装することも、リソースにアクセスするためのいくつかのファサード関数を記述することも非常に簡単なはずです。

于 2008-09-16T14:15:31.290 に答える