尝试使用 dlopen() 打开共享库,看看它是否加载,如果没有加载,dlerror() 会告诉您什么。我在 Windows 上总是遇到类似的问题。 LoadLibrary()/GetLastError() 救了我很多次(上次是因为某些 libiconv/libintl DLL 的版本错误)。在插件上运行 ldd 也可能有帮助。
如果 dlopen() 工作正常,请尝试使用 QPluginLoader 加载插件。如果未加载,请检查插件的 buildkey。我通常通过在插件上运行字符串然后查找“buildkey”或“QT_PLUGIN_VERIFICATION_DATA”等字符串来完成此操作。只需查看构建密钥及其周围的内容可能会给您一个想法。例如,您可能会意识到您已经在发布模式下编译了插件,而您的应用程序是在调试模式下编译的。在这种情况下,构建密钥将不匹配,并且插件将无法加载。构建密钥中的所有内容都必须与您的配置匹配。请注意,版本和构建密钥的检查方式不同:构建密钥必须完全匹配(或匹配一些称为 QT_BUILD_KEY_COMPAT 的黑魔法),但在版本中只有主要版本必须完全匹配,次要版本必须是 Qt 的版本插件是用 或更高版本编译的,并且补丁级别被忽略。因此,如果您的插件是使用 Qt 4.x.y 编译的,那么它将适用于 Qt 版本 4.z.*(其中 z>=x)。这实际上是有道理的。
如果构建密钥看起来没问题(如果您达到了这一点,则不太可能),您可能希望查看 QLibraryPrivate::isPlugin() 源代码以找出问题所在,但这对我来说似乎不是一件容易的事(尽管在调试器中运行它可能会有所帮助)。
如果 QPluginLoader 确实加载了插件,请检查它是否位于正确的目录中并且具有正确的权限。如果此时您仍然没有解决问题,那么是时候查看实际加载这些插件的 SQL 模块源代码了。但这是极不可能的。我多次遇到这个问题,总是要么库未加载,要么构建密钥不匹配。
QPluginLoader 成功加载插件后的另一种方法是使用 strace 来确定程序是否至少尝试打开插件文件。在 strace 输出中搜索诸如“sqldrivers”或“plugins”之类的内容也应该给出 Qt 搜索其插件(特别是 SQL 驱动程序)的目录。
Update
是否可以将驱动程序编译为静态插件而不用担心任何事情?咱们试试吧:
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
它编译得很好,现在我在 QTDIR/plugins/sqldrivers 中得到了 libqsqlpsql.a (发布)和 libqsqlpsqld.a (调试)(它isWindows 上正确的位置)。我在这里使用 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
请注意,我必须手动链接到 libpq,否则链接器会抱怨未定义的引用。有趣的是,qmake 知道 qsqlpsql 位于 QTDIR/plugins/sqldrivers 中,并相应地设置编译器和链接器选项。所以它仍然需要在正确的地方工作,只是你不必担心你的用户遇到同样的问题,因为它只在编译期间使用。另一种选择是只使用LIBS+=-Lpath/to/plugin LIBS+=-lqsqlpsql
代替QTPLUGIN+=qsqlpsql
,至少文档说它应该有效,但我还没有测试过。
为了让应用程序实际使用该插件,我必须将以下内容放入我的主单元(CPP 文件)中:
#include <QtPlugin>
Q_IMPORT_PLUGIN(qsqlpsql)
有用!另外,从我从来源中了解到的情况来看,只有在动态加载插件时才会检查构建密钥和版本(所有相关内容都在 QLibrary 的私有类中,甚至不在 QPluginLoader 中)。因此,生成的可执行文件可能(也可能不会,取决于二进制兼容性)即使在不同版本和构建的 Qt 上也能工作,尽管与旧版本一起使用可能会触发一些稍后修复的错误。
还值得注意的是,加载 SQL 驱动程序的顺序是这样的:使用静态链接到 Qt 的驱动程序(如果可用),然后查找使用 QSqlDatabase::registerSqlDriver() 手动注册的驱动程序,然后查找静态导入到应用程序中的驱动程序(上面介绍的方式),最后尝试加载一个共享插件。因此,当您静态链接时,您的用户将无法使用他们可能已经拥有的动态链接驱动程序,但可以使用静态链接到 Qt 中的驱动程序(如在 Ubuntu 中)。