Android Eclipse项目中的Qt C++库:未加载QSQLITE驱动程序

sas*_*alm 7 c++ eclipse qt android

我已经创建了一个使用Qt SQL打开SQLite数据库的Qt动态库,但是我收到了这个错误:

QSqlDatabase: QSQLITE driver not loaded
QSqlDatabase: available drivers: 
Run Code Online (Sandbox Code Playgroud)

DLL作为Qt Android应用程序的一部分工作正常,但是我需要通过JNI从Eclipse中开发的现有Java应用程序中使用它.

这是再现问题的最短示例代码.我从Java加载库并调用其init()方法:

System.loadLibrary("plugins_sqldrivers_libqsqlite");
System.loadLibrary("Qt5Sql");
System.loadLibrary("MyQtLib");
MyQtLib.init();
Run Code Online (Sandbox Code Playgroud)

在Qt库中我只调用QSqlDatabase :: addDatabase():

JNIEXPORT void JNICALL Java_test_MyQtLib_foo(JNIEnv *, jclass)
{
    // Manually create a QCoreApplication instance.
    int argc = 1;
    static char arg[] = "";
    static char *arg2 = arg;
    app = new QCoreApplication(argc, &arg2);
    // Try to add an SQLite db connection.
    QSqlDatabase::addDatabase("QSQLITE");
}
Run Code Online (Sandbox Code Playgroud)

由于错误是QSQLITE driver not loaded,并且Qt库在Qt应用程序内部工作,我假设Qt正在进行一些我缺少的初始化.

但这并没有消除错误,所以它必须是别的东西.通常,Qt应用程序将使用QtApplication.javaQtActivity.java来执行一些初始化,因此他们必须在那里做更多我不做的事情.

sas*_*alm 5

最终,我进入了Qt源码,以了解如何加载SQLITE插件(至少对于桌面版本而言)。

相关的函数是QFactoryLoader :: update()。在其中,我注意到它会迭代以下目录中的所有目录QCoreApplication::libraryPaths()

QStringList paths = QCoreApplication::libraryPaths();
for (int i = 0; i < paths.count(); ++i) {
Run Code Online (Sandbox Code Playgroud)

如果它们中的任何一个都有一个名为“ sqldrivers”的子目录,它将进入其中并尝试将所有动态库加载到该子目录中。

然后,我在直接从Qt Creator运行的测试项目中打印出库路径qDebug() << a.libraryPaths();,然后看到了该路径- /data/data/org.qtproject.example.untitled/qt-reserved-files/plugins。在我的android手机上的此目录中,有一个名为的子目录sqldrivers,其中包含一个文件- libqsqlite.so

然后,我检查了.java文件,并确实QtActivity::startApp()添加了库路径:

boolean bundlingQtLibs = false;
if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
    && m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
    localPrefix = getApplicationInfo().dataDir + "/";
    pluginsPrefix = localPrefix + "qt-reserved-files/";
    cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
    extractBundledPluginsAndImports(pluginsPrefix);
    bundlingQtLibs = true;
}
Run Code Online (Sandbox Code Playgroud)

解决方案将是确保sqldrivers/libqsqlite.so电话上有某个位置,然后使用将该文件夹的父文件夹添加sqldrivers到库路径QCoreApplication::addLibraryPath()