pluginLoader.instance() returns nullptr if one class is present in qt_add_plugin()
-
Hello,
I discover the Qt plugin world and I am facing a weird issue.Here is the CMakeLists.txt of my plugin
qt_add_plugin(MyPlugin SHARED CLASS_NAME WidgetPlugin MyPlugin.cpp MyPlugin.h classA.cpp classA.h classB.cpp classB.h classC.cpp classC.h ... classG.cpp classG.h classH.cpp classH.h ) set_target_properties(MyPlugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/plugins" ) target_include_directories(MyPlugin PRIVATE ../dirWhereInterfaceIsDefined ) target_link_libraries(MyPlugin PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Network Qt6::Positioning Qt6::Svg Qt6::SvgWidgets ) install(TARGETS MyPlugin RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugins" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/plugins" )
Not here is the snippet I use to load the plugin
bool MyApplication::loadPlugin() { QDir pluginsDir(QCoreApplication::applicationDirPath()); pluginsDir.cdUp(); QString dirName("plugins"); bool ok = pluginsDir.cd(dirName); if(!ok) qDebug() << "The directory \"" << dirName << "\" does not exist!"; const QStringList entries = pluginsDir.entryList(QDir::Files); for (const QString &fileName : entries) { QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName)); qDebug() << "Loading" << fileName << "..."; QObject *plugin = pluginLoader.instance(); if (plugin) { populateTabs(plugin); return true; } qDebug() << "pluginLoader.instance() failed"; pluginLoader.unload(); } return false; }
The class classH depends on all the other classes and is the main class of the plugins. The problem is that with CMakeLists.txt like this, the
plugin
QObject is always a nullptr.What I have done so far is to comment out all the lines in qt_add_plugin() one by one to see which class is broken. What I discovered is that the class classG is broken. If I comment the classG line and remove the classG dependency in classH, the plugin loader returns a non-zero object, which is perfect.
The class classG depends on classA and classB, so it is not clear to me what could cause the plugin to be a nullptr when classG is present.
This is a bit tricky for me because this classG works fine when I am not using it in a plugin system, i.e. it is used within a single application.
Do you have any idea of what could cause this behaviour?
-
@odelaune
Changing the debug statement toqDebug() << __FUNCTION__ << fileName << pluginLoader.errorString();
maybe sheds more light on the matter.
Is plugin actually built? That can be ensured by adding
find_package(MyPlugin)
to the toplevel CMakeLists.txt.
I assume that the libraries in thetarget_link_libraries
statement have all been found before. It wouldn't hurt adding afind_package
in the plugin's CMakeLists.txt as well.On a side note: The code for loading will iterate over all files found in the application directory. So the error output will be quite noisy. Might be worth considering a subdirectory for the plugin, or filtering the names for an expected plugin name convention.
On a side-side note: Returning true after having found the first plugin will never allow having more than one plugin. I guess that's intentional.
-
@odelaune
Changing the debug statement toqDebug() << __FUNCTION__ << fileName << pluginLoader.errorString();
maybe sheds more light on the matter.
Is plugin actually built? That can be ensured by adding
find_package(MyPlugin)
to the toplevel CMakeLists.txt.
I assume that the libraries in thetarget_link_libraries
statement have all been found before. It wouldn't hurt adding afind_package
in the plugin's CMakeLists.txt as well.On a side note: The code for loading will iterate over all files found in the application directory. So the error output will be quite noisy. Might be worth considering a subdirectory for the plugin, or filtering the names for an expected plugin name convention.
On a side-side note: Returning true after having found the first plugin will never allow having more than one plugin. I guess that's intentional.
-
Thank you very much. Using
pluginLoader.errorString()
helped me to find the problem (a global variable was missing in classG, adding it makes the plugin load correctly).I am discovering the plugin world so I was not aware about errorString(). Thanks for all your tips.
-
-
@odelaune Thanks, pls mark the thread solved!