簡體   English   中英

將 sqlite 數據庫嵌入到 c++ 可執行文件中

[英]Embed sqlite database into c++ executable

我認為我的問題與這個問題有關,但是那個問題是關於 png 的,我不知道如何將其轉化為我的情況。

我在以 .db 結尾的文件中使用 sqlite 創建了一個數據庫。 現在我有一個只從這個數據庫中讀取的程序。 有沒有辦法將數據庫文件包含到可執行文件中?

現在,如果我編譯,我必須將可執行文件和文件放在一起。 可以通過將數據庫文件放在絕對路徑中來刪除這種依賴關系,但我也在處理 hpc 集群,所以這不起作用。 我需要一個相對路徑,以便 db 文件與我的 main.cpp 處於同一層次結構,但我希望能夠在不復制 db 文件的情況下復制可執行文件,因此在某種程度上,db 文件已經是可執行文件的一部分。

假設你在你的二進制文件中嵌入了 SQLite 數據庫,你有一個const char *embedded_startsize_t embedded_length embedding_length 表示數據庫的開始和長度。

答案取決於您願意投入多少工作:

  1. 最簡單的方法是創建一個臨時文件,在其中轉儲 sqlite 字節,然后像對待任何其他 SQLite 數據庫一樣對待它。
FILE *db = tmpfile();
fwrite(embedded_start, embedded_length, 1, db);
fflush(db);
std::string path = std::string{"/proc/self/fd/"} + std::to_string(fileno(db));
sqlite3_open_v2(path.c_str(), &dbconn, SQLITE_OPEN_READONLY, nullptr);
  1. 如果您不希望文件在磁盤上逗留,請使用 memfd_create 創建一個文件描述符,將字節加載到其中,然后讓 SQLite 打開/proc/self/fd/X
  2. 實現在內存中執行所有操作的自定義 VFS。 這個鏈接可能是一個開始。

sqlite3_deserialize例程,它從數組中獲取數據庫轉儲並將其“加載”到提供的數據庫連接中。 結合內存數據庫,它可以用來完成你想要的。

// Plain dump of file. Made with xxd -i
unisgned char db_dump[] = {0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20 ....etc

// Create empty, readonly in-memory db
sqlite3* db = NULL;
sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READONLY, NULL);

// Reopen db with dump of other one
rc = sqlite3_deserialize(db, "main", db_dump, sizeof(db_dump), sizeof(db_dump),
        SQLITE_DESERIALIZE_READONLY);

完整的、可運行的示例(太長,無法在此處發布)

append 一些東西(例如病毒,但在這種情況下是數據庫)到可執行文件的末尾存在一個古老的技巧。 可執行文件通常可以正常工作,但您也可以讀取(甚至可能寫入)數據庫。 已經提到的自定義 VFS 可以幫助您完成這項任務。

另一種解決方案可能是將數據庫視為一種資源,例如 Windows 資源或 Qt 資源。 然后,您可以將數據庫壓縮/編譯為可執行文件。 訪問資源(數據庫)將取決於您使用的框架。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM