如何让Qt知道QMYSQL驱动程序

Rap*_*ael 8 qt qtsql

我正在尝试从Qt应用程序访问MySql数据库,但是我收到以下错误:

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

我发现这很奇怪的原因我在我的Qt文件夹上有libqsqlmysql.so.我甚至尝试将MySql驱动程序编译为静态插件,并将其添加到我的.pro文件中:

QTPLUGIN += qsqlmysql
Run Code Online (Sandbox Code Playgroud)

但是这也会产生相同的运行时错误(它必须找到插件导致编译应用程序时没有错误)

我错过了什么?我想避免从源代码编译Qt,因为这也必须在部署机器上无缝工作.

顺便说一句:即使我在Linux上开发和测试,我也需要支持Windows.我会在Windows上遇到同样的问题吗?如何在Linux和Windows中编译和链接MySql驱动程序?

解决方案:

按照@ Sergey的推荐,我做了一个应用程序重定向输出到grep,所以我可以搜索'mysql',我惊讶的是应用程序没有在QTDIR/plugins/sqldrivers中找到我有libqsqlmysql.so的插件,它在看QTDIR/lib目录下.将插件复制到lib文件夹后,MySql连接正常工作.

Ser*_*nov 10

尝试用dlopen()打开共享库,看看它是否加载,如果没有,dlerror()会告诉你.我总是在Windows上遇到类似的问题.LoadLibrary()/ GetLastError()多次保存(上次是由于某些libiconv/libintl DLL的错误版本).在插件上运行ldd也可能有所帮助.

如果dlopen()工作正常,请尝试使用QPluginLoader加载插件.如果没有加载,则检查插件的buildkey.我通常通过在插件上运行字符串然后查找"buildkey"或"QT_PLUGIN_VERIFICATION_DATA"之类的字符串来做脏话.只需查看构建密钥及其周围可能会给您一个想法.例如,您可能会意识到在应用程序以调试模式编译时,您已在发布模式下编译了插件.在这种情况下,构建密钥将不匹配,插件将不会加载.构建密钥中的所有内容都必须与您的配置相匹配.请注意,版本和构建密钥的检查方式不同:构建密钥必须完全匹配(或匹配一些名为QT_BUILD_KEY_COMPAT的黑魔法),但在版本中只有主要版本必须完全匹配,次要版本必须是Qt的版本使用或稍后编译插件,并忽略补丁级别.因此,如果您的插件是使用Qt 4.xy编译的,那么它将适用于Qt版本4.z.*,其中z> = x.这实际上是有道理的.

如果构建密钥看起来没问题(如果你达到这一点这是不可能的),你可能希望查看QLibraryPrivate :: isPlugin()源代码以找出错误,但对我来说这看起来不是一件容易的事. (尽管在调试器中运行它可能有所帮助).

如果QPluginLoader确实加载了插件,请检查它是否在正确的目录中并具有正确的权限.如果到目前为止仍然没有解决问题,那么现在是时候查看实际加载这些插件的SQL模块源代码了.但这种可能性极小.我遇到了很多次这个问题,并且总是要么没有加载库,要么构建密钥不匹配.

在QPluginLoader成功加载插件之后的另一种方法是使用strace来确定程序是否至少尝试打开插件文件.在strace输出中搜索"sqldrivers"或"plugins"之类的东西也应该放弃Qt搜索其插件的目录,特别是SQL驱动程序.

更新

是否可以将驱动程序编译为静态插件而不用担心什么?我们试试吧:

d:\Qt4\src\plugins\sqldrivers\psql>qmake CONFIG+=static LIBS+=-Ld:/programs/Post
greSQL/lib INCLUDEPATH+=d:/programs/PostgreSQL/include
d:\Qt4\src\plugins\sqldrivers\psql>make
Run Code Online (Sandbox Code Playgroud)

它编译得很好,现在我在QTDIR/plugins/sqldrivers中得到了libqsqlpsql.a(release)和libqsqlpsqld.a(debug)(它在Windows上正确的位置).我在这里使用的是PostgreSQL驱动程序,但我认为对于MySQL我没有安装它会有什么不同.好的,让我们用它编译一些真正的程序:

d:\alqualos\pr\archserv>qmake QTPLUGIN+=qsqlpsql PREFIX=d:/alqualos LIBS+=-Ld:/g
nu/lib INCLUDEPATH+=d:/gnu/include LIBS+=-Ld:/programs/PostgreSQL/lib LIBS+=-lpq
Run Code Online (Sandbox Code Playgroud)

请注意,我必须手动链接到libpq,否则链接器会抱怨未定义的引用.有趣的是,qmake知道qsqlpsql位于QTDIR/plugins/sqldrivers中,并相应地设置编译器和链接器选项.因此,它仍然需要在正确的位置工作,只有您不必担心您的用户遇到同样的问题,因为它只在编译期间使用.另一种方法是使用LIBS+=-Lpath/to/plugin LIBS+=-lqsqlpsql而不是QTPLUGIN+=qsqlpsql,至少文档说它应该工作,但我没有测试它.

为了让应用程序实际使用插件,我必须将以下内容放在我的主单元(CPP文件)中:

#include <QtPlugin>
Q_IMPORT_PLUGIN(qsqlpsql)
Run Code Online (Sandbox Code Playgroud)

有用!此外,从我从源头中可以看出,只有在动态加载插件时才会检查构建密钥和版本(所有相关内容都在QLibrary的私有类中,甚至不在QPluginLoader中).因此,生成的可执行文件可能(或可能不是,取决于二进制兼容性)甚至可以使用Qt的不同版本和版本,尽管将其与旧版本一起使用可能会触发稍后修复的一些错误.

还值得注意的是,加载SQL驱动程序的顺序是:使用静态链接到Qt的驱动程序(如果可用),然后查找使用QSqlDatabase :: registerSqlDriver()手动注册的驱动程序,然后查找静态导入到应用程序中的驱动程序(上面描述的方式),最后尝试加载共享插件.因此,当您静态链接时,您的用户将无法使用他们可能已经拥有的动态链接驱动程序,但可以使用静态链接到Qt的驱动程序(如在Ubuntu中).