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

2023-09-06 08:55:10 作者:花落、卻未謝

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

I've created a Qt dynamic lib that uses Qt SQL to open an SQLite database, but I'm getting this error:

QSqlDatabase: QSQLITE driver not loaded
QSqlDatabase: available drivers: 

是工作的罚款作为一个Qt的Andr​​oid应用程序的一部分的DLL,但是我需要通过JNI从Eclipse开发的现有Java应用程序中使用它。

The DLL was working fine as part of a Qt Android application, however I need to use it through JNI from an existing Java application developed in Eclipse.

这是最短的例子code能重现问题。我从Java加载库并调用它的的init()方法:

This is the shortest example code that reproduces the problem. I load the library from Java and call its init() method:

System.loadLibrary("plugins_sqldrivers_libqsqlite");
System.loadLibrary("Qt5Sql");
System.loadLibrary("MyQtLib");
MyQtLib.init();

和Qt库里面我只是叫QSqlDatabase :: addDatabase():

And inside the Qt library I just call 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");
}

由于误差 QSQLITE驱动程序未加载,以及Qt库正在一个Qt应用程序中,我认为Qt的是做一些初始化我失踪。

Since the error is QSQLITE driver not loaded, and the Qt library was working inside a Qt application, I assume that Qt is doing some initialization that I'm missing.

但这并不能消除错误,所以它必须是别的东西。通常情况下,Qt应用程序将使用 QtApplication.java 和 QtActivity.java 进行一些初始化,所以他们必须做更多的东西那里,我不这样做。

But this didn't remove the error, so it must be something else. Normally, the Qt application will use QtApplication.java and QtActivity.java to perform some initialization, so they must be doing something more there that I'm not doing.

推荐答案

最后,我走进了Qt的来源看SQLite的插件怎么装(用于桌面版本至少)。

Eventually I stepped into the Qt sources to see how the SQLITE plugin is loaded (for the desktop build at least).

相关功能是 QFactoryLoader ::更新()。在这里面我注意到,它遍历所有的目录中 QCoreApplication :: libraryPaths()

The relevant function was QFactoryLoader::update(). In it I noticed that it iterates all the directories in QCoreApplication::libraryPaths():

QStringList paths = QCoreApplication::libraryPaths();
for (int i = 0; i < paths.count(); ++i) {

如果任何人有一个名为sqldrivers的子目录,它走了进去,并尝试加载所有的动态库中的子目录。

If any of them has a sub-directory named "sqldrivers", it goes inside it and tries to load all the dynamic libraries in that sub-directory.

然后我打印出来的测试项目中,我直接从Qt Creator的运行库的路径 - qDebug()&LT;&LT; a.libraryPaths(); ,我看到了这条道路 - /data/data/org.qtproject.example.untitled/qt-reserved-files/plugins 。在我的Andr​​oid手机在这个目录有一个叫 sqldrivers 子目录,包含一个文件 - libqsqlite.so

I then printed out the library paths in a test project I ran directly from Qt Creator - qDebug() << a.libraryPaths();, and I saw this path - /data/data/org.qtproject.example.untitled/qt-reserved-files/plugins. In this directory on my android phone there was a subdirectory named sqldrivers, that contained a single file - libqsqlite.so.

然后我检查了.java文件,而事实上 QtActivity ::的startApp()将库路径:

I then checked the .java files, and indeed QtActivity::startApp() adds the library path:

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;
}

解决方案则是确保有一个 sqldrivers / libqsqlite.so 在手机上的某个地方,然后添加的父文件夹sqldrivers 使用库路径 QCoreApplication :: addLibraryPath()

The solution then would be to ensure that there is a sqldrivers/libqsqlite.so somewhere on the phone, and then add the parent folder of sqldrivers to the library path using QCoreApplication::addLibraryPath().

 
精彩推荐
图片推荐