gcc 将sqlite数据库嵌入c++可执行文件

8fq7wneg  于 2022-11-13  发布在  SQLite
关注(0)|答案(3)|浏览(200)

我想我的问题与this一个有关,但那个一个是谈论一个png,我不知道如何翻译到我的情况。
我在一个以. db结尾的文件中用sqlite创建了一个数据库。现在我有了一个只从这个数据库读取数据的程序。有没有办法将数据库文件包含到可执行文件中?
现在如果我编译,我必须将可执行文件和文件放在一起。通过将数据库文件放在绝对路径中可以消除这种依赖性,但我也在hpc集群上工作,所以这不起作用。我需要一个相对路径,这样db文件就可以和我的main.cpp在同一个层次结构中,但我希望能够复制可执行文件,而不必复制db文件。因此在某种程度上,DB文件已经是可执行文件的一部分。

kt06eoxx

kt06eoxx1#

假设您在二进制文件中嵌入了SQLite数据库,那么您将有一个const char *embedded_startsize_t embedded_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
1.实现一个在内存中执行所有操作的自定义VFS。This link可能是一个开始。

1mrurvl1

1mrurvl12#

有一个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);

Full, runnable example(太长,无法在此处发布)

qojgxg4l

qojgxg4l3#

有一个古老的技巧,就是在可执行文件的末尾附加一些内容(比如病毒,但在本例中是数据库)。可执行文件通常会正常工作,但您也可以读取(甚至写入)数据库。前面提到的自定义VFS可以帮助您完成这项任务。
另一种解决方案可能是将数据库视为一种资源,如Windows资源或Qt资源。然后,您可以将数据库压缩/编译为可执行文件。访问资源(数据库)将取决于您使用的框架。

相关问题