Qt Plugin Loading fails (specified module could not be found) - qt

For some reason I am unable to load my plugins anymore, although it has worked previously. I have a plugin loader code in my MainWindow, which is supposed to load every .dll found in a specific folder. The MainWindow Code contains the following:
Interface
#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H
#include <QtPlugin>
// forward declarations
class MainWindow;
struct P3DData;
class PluginInterface
{
public:
virtual bool createPublisher(MainWindow*, P3DData*) = 0;
};
#define PLUGIN_INTERFACE_iid "PluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PLUGIN_INTERFACE_iid)
#endif // PLUGININTERFACE_H
loadPlugins()
bool MainWindow::loadPlugins()
{
QDir pluginsDir(qApp->applicationDirPath());
pluginsDir.cd("plugins");
const auto entryList = pluginsDir.entryList(QDir::Files);
for(const QString &fileName : entryList)
{
QString dllPath = pluginsDir.absoluteFilePath(fileName);
QPluginLoader* loader = new QPluginLoader(dllPath);
loaderList.push_back(loader);
QObject *plugin = loader->instance();
if (plugin)
{
pluginList.push_back(qobject_cast<PluginInterface *>(plugin));
pluginList.last()->createPublisher(this, simDataPtr);
pluginCount++;
continue;
}
else
{
qDebug() << "[PluginLoader] '" + fileName + "': " + loader->errorString();
delete loaderList.takeLast();
}
}
}
Besides my MainWindow, there is another subdir in my project, which is the plugin "Position". The plugin is deployed into the correct "plugins" folder, which the loadPlugin() method from the MainWindow iterates through. The plugin uses following code to implement the interface:
#include <QObject>
#include "MainWindow.h"
class PositionPublisher : public QObject, PluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "PluginInterface")
Q_INTERFACES(PluginInterface)
public:
PositionPublisher();
~PositionPublisher();
bool createPublisher(MainWindow* _window, P3DData* _simDataPtr) override;
//...
};
When trying to run loadPlugins() now, it checks the correct Position.dll file but the "if(plugin)" part returns false and loader->errorString() is executed giving the following error:
[PluginLoader] 'Position.dll': Cannot load library
F:\DEV\build\simNET\bin\plugins\Position.dll: Cannot find the
specified module.
I have already checked and tried the following:
the Plugins folder actually contains the Position.dll file
both projects (MainWindow and Plugin) are built in release mode
the dependencies of the plugin (two libs) exist and the specified path in the pro file is correct
.pro file of plugin:
QT += widgets
TEMPLATE = lib
CONFIG += c++11
CONFIG += plugin
CONFIG += release
SOURCES += \
Position.cpp \
PositionPubSubTypes.cpp \
PositionPublisher.cpp
HEADERS += \
Position.h \
PositionPubSubTypes.h \
PositionPublisher.h
DISTFILES += \
Position.idl
INCLUDEPATH += ../../application
TARGET = $$qtLibraryTarget(Position)
DESTDIR = ../../bin/plugins
INCLUDEPATH += "F:/DEV/prog/FastRTPSv1.5/include"
DEPENDPATH += "F:/DEV/prog/FastRTPSv1.5/include"
LIBS += -L"F:/DEV/prog/FastRTPSv1.5/lib/x64Win64VS2015" -lfastrtps-1.5
PRE_TARGETDEPS += F:/DEV/prog/FastRTPSv1.5/lib/x64Win64VS2015/fastrtps-1.5.lib
INCLUDEPATH += 'F:/Programme/Prepar3D v4/SDK/inc/SimConnect'
DEPENDPATH += 'F:/Programme/Prepar3D v4/SDK/inc/SimConnect'
LIBS += -L'F:/Programme/Prepar3D v4/SDK/lib/SimConnect' -lSimConnect
PRE_TARGETDEPS += 'F:/Programme/Prepar3D v4/SDK/lib/SimConnect/SimConnect.lib'
Does anyone have an idea why it does not load the plugin??

Qt plugin loader is trying to tell you that a Qt module used in your plugin doesn't exist so first you need to check which Qt modules your plugin depends on then,
If you're trying to run the application from Qt Creator itself, and it gives you this error, then maybe the DLL file got deleted for some reason or you're trying to use the plugin with a Qt version that doesn't have its needed modules. (for example, Qt6 doesn't contain the QtSerialPort module but Qt5 did (at the time of writing this)).
If you're trying to run the application directly outside Qt Creator then you need to copy the required module's dll file into your applications root directory.

Related

Qt library problem : Can't link a dynamic library i created to a project

I created a c++ dynamic library from qt creator. and when i try to implement it in a qwidget application for testing. I get some errors.
Include and library paths must all be correct. as i have the .a file qt needs and include path is also correct.
my project's .pro file is;
QT += core gui multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = testlib2
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
SOURCES +=
main.cpp
mainwindow.cpp
HEADERS +=
mainwindow.h
FORMS +=
mainwindow.ui
Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
unix|win32: LIBS += -L$$PWD/../build-tonegenlib-Desktop_Qt_5_12_1_MinGW_64_bit-Debug/debug/ -ltonegenlib
INCLUDEPATH += $$PWD/../tonegenlib
DEPENDPATH += $$PWD/../tonegenlib
and the compile error is this;
debug/mainwindow.o: In function MainWindow::MainWindow(QWidget*)': C:\QT_workspace\build-testlib2-Desktop_Qt_5_12_1_MinGW_64_bit-Debug/../testlib2/mainwindow.cpp:6: undefined reference to__imp__ZN10TonegenlibC1Ev'
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: *** [Makefile.Debug:69: debug/testlib2.exe] Error 1
mingw32-make: *** [Makefile:38: debug] Error 2
mingw32-make[1]: Leaving directory 'C:/QT_workspace/build-testlib2-Desktop_Qt_5_12_1_MinGW_64_bit-Debug'
01:29:22: The process "C:\Qt\Qt5.12.1\Tools\mingw730_64\bin\mingw32-make.exe" exited with code 2.
Error while building/deploying project testlib2 (kit: Desktop Qt 5.12.1 MinGW 64-bit)
When executing step "Make"
01:29:22: Elapsed time: 00:01.
this is the header file of the project;
#include <QMainWindow>
#include <tonegenlib.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
Tonegenlib tonegen;
void test();
private:
Ui::MainWindow *ui;
};
and this is the .cpp
void MainWindow::test()
{
tonegen.m_freq = 240;
tonegen.playAudio();
}
when i add the library and build the project without a code about the library it compiles it without error. but when i try to call a function it breaks.
Thank you so much for your help

Qt Multimedia - how to force read tags from media file

It seems to be QMediaPlayer doesn't read tags of playlist files without of executing method play() of current track. Is there a way to force read tags from QMediaPlayer playlist without of playing it?
Sorry if this if a noob question, but I spent a lot of time for searches.
Thanks
Don't waste your time to use QMediaPlayer to read tags (this solution works good, but difficult for many files in list), simply use TagLib or another open-source library.
For example, 3 simple steps to use TagLib in Qt:
1.Compile taglib from source:
$ pwd
/home/user/taglib-1.9.1
$ cmake .
$ make
It's enough to deploy working instance of tag library. Really :)
2.Include headers and library in your project, simply add this or your custom path to project file:
unix:!macx: LIBS += -L$$PWD/3rdparty/taglib-1.9.1/taglib/ -ltag
INCLUDEPATH += $$PWD/3rdparty/taglib-1.9.1/taglib/Headers
DEPENDPATH += $$PWD/3rdparty/taglib-1.9.1/taglib/Headers
3.Use it, very simple function to get media tags from files, in this example artist and title of track:
#include <fileref.h>
#include <tag.h>
QString gettags(QString mediafile){
QString string;
TagLib::FileRef file(mediafile.toUtf8());
TagLib::String artist_string = file.tag()->artist();
TagLib::String title_string = file.tag()->title();
QString artist = QString::fromStdWString(artist_string.toWString());
QString title = QString::fromStdWString(title_string.toWString());
string = artist + " - " + title;
return string;
}
For the current QT/OSX, use this project file snippet (change paths for your system)
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11
LIBS += -L/Users/sir/prg.qt/TuneMerge/taglib-1.11.1/taglib/ -ltag -lz
INCLUDEPATH += /Users/sir/prg.qt/TuneMerge/taglib-1.11.1/
INCLUDEPATH += /Users/sir/prg.qt/TuneMerge/taglib-1.11.1/taglib/
INCLUDEPATH += /Users/sir/prg.qt/TuneMerge/taglib-1.11.1/taglib/toolkit/
DEPENDPATH += /Users/sir/prg.qt/TuneMerge/taglib-1.11.1/taglib

How to link to qaxserver.def entities properly

all
I'm trying to create ActiveX server with Qt5.2.0.
According to some pieces of information I have, to create a simple ActiveX server (which exports one object) it's enough to:
have such .pro file
TEMPLATE = lib
CONFIG += dll axserver
TARGET = simpleServer
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
QT += core
RC_FILE = qaxserver.rc
DEF_FILE = qaxserver.def
HEADERS += myserver.h
SOURCES += main.cpp
SOURCES += myserver.cpp
have such main.cpp file
#include "ActiveQt/QAxFactory"
#include "myserver.h"
QAXFACTORY_DEFAULT( MyServer, 5 id's )
the class should inherit QWidget and QAxBindable
there should be file qaxserver.rc. in my case it's content is 1 TYPELIB "simpleServer.pro"
there should be fie qaxserver.def with default contents:
; mfc_test.def : Declares the module parameters.
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DumpIDL PRIVATE
the problem is that these 5 names are undefined for Visual Studio's linker.
How to solve the problem?
the error is:
error LNK2001: unresolved external symbol DllCanUnloadNow
need to add QT += axserver in .pro file

QT Systray icon appears next to launcher on Ubuntu instead of on the panel

I am new to QT and need to build an app with an app-indicator. As QT seems easier than GTK+, I am making it in QT.
I would mention that I have sni-qt installed and app indicators of vlc and skype appear normal on the panel. I am using QT5 on Ubuntu 13.04 64-bit.
I followed this tutorial step by step: http://qt-project.org/doc/qt-4.8/desktop-systray.html
But when I run it, here's how it appears (The cross is the icon I am using):
How do I fix this?
I'm afraid that Qt5 is not supported by sni-qt at the moment, so you either have to wait for a new release that will support it, or code it using gtk+ and libappindicator using this guide. There are even examples for various of languages. Since Qt5 also distributes GLib events that makes the integration a lot more easier. First you need to find out whether you're running on Unity or not (to support more desktops than just unity), that you can do by retrieving XDG_CURRENT_DESKTOP environment variable and if it returns Unity you create appindicator, otherwise create QSystemTrayIcon.
First you need to include required headers:
#undefine signals
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
}
#define signals public
Since app-indicator directly uses "signals" name we need to undefine the default Qt "keyword" signals which normally translates to public. Then, since we're coding C++ and libappindicator is coded in C we need to use extern "C" not to use C++ name mangling.
Next create the AppIndicator/QSystemTrayIcon based on what desktop are we on:
QString desktop;
bool is_unity;
desktop = getenv("XDG_CURRENT_DESKTOP");
is_unity = (desktop.toLower() == "unity");
if (is_unity) {
AppIndicator *indicator;
GtkWidget *menu, *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(item, "activate",
G_CALLBACK(quitIndicator), qApp); // We cannot connect
// gtk signal and qt slot so we need to create proxy
// function later on, we pass qApp pointer as an argument.
// This is useful when we need to call signals on "this"
//object so external function can access current object
gtk_widget_show(item);
indicator = app_indicator_new(
"unique-application-name",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS
);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_menu(indicator, GTK_MENU(menu));
} else {
QSystemTrayIcon *icon;
QMenu *m = new QMenu();
m->addAction(tr("Quit"), qApp, SLOT(quit()));
}
Finally we create the proxy function to call Qt signal from it, to declare the function we need to use extern "C" so there will not be any undefined behaviour.
extern "C" {
void quitIndicator(GtkMenu *, gpointer);
}
Now the proxy function:
void quitIndicator(GtkMenu *menu, gpointer data) {
Q_UNUSED(menu);
QApplication *self = static_cast<QApplication *>(data);
self->quit();
}
Just wanted to add, for anyone that is using Qt and trying to show a app indicator in Ubuntu 13+ as others have mentioned sni-qt is not working, I was able to use the above reply to make a Qt app that works, still trying to get the icon to change and show popup messages, but this is a great start, once i get the icon and message to work i might post it out on my site Voidrealms.com:
Be sure to do sudo apt-get install libappindicator-dev
Make a new project with a QDialog in it and modify as seen below:
Pro file:
#-------------------------------------------------
#
# Project created by QtCreator 2014-03-28T20:34:54
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = PluginServiceGUI
TEMPLATE = app
# includes for the libappindicator
# /usr/lib/x86_64-linux-gnu libglib-2.0.a
INCLUDEPATH += "/usr/include/libappindicator-0.1"
INCLUDEPATH += "/usr/include/gtk-2.0"
INCLUDEPATH += "/usr/include/glib-2.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/include/cairo"
INCLUDEPATH += "/usr/include/pango-1.0"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
INCLUDEPATH += "/usr/include/atk-1.0"
LIBS += -L/usr/lib/x86_64-linux-gnu -lgobject-2.0
LIBS += -L/usr/lib/x86_64-linux-gnu -lappindicator
LIBS += -L/usr/lib/x86_64-linux-gnu -lgtk-x11-2.0
#These seem to not be needed
#LIBS += -L/usr/lib/x86_64-linux-gnu -lcairo
#LIBS += -L/usr/lib/x86_64-linux-gnu -lpango-1.0
#LIBS += -L/usr/lib/x86_64-linux-gnu -lglib-2.0
# end incudes for libappindicator
SOURCES += main.cpp\
dialog.cpp
HEADERS += dialog.h
FORMS += dialog.ui
RESOURCES += \
resources.qrc
In the main.cpp
#include "dialog.h"
#include <QApplication>
#include <QtGui>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QSystemTrayIcon>
#include <QMenu>
// http://stackoverflow.com/questions/17193307/qt-systray-icon-appears-next-to-launcher-on-ubuntu-instead-of-on-the-panel
// requires libappindicator-dev
// sudo apt-get install libappindicator-dev
// installs the headers in: /usr/include/libappindicator-0.1/libappindicator
#undef signals
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
void quitIndicator(GtkMenu *, gpointer);
}
#define signals public
void quitIndicator(GtkMenu *menu, gpointer data) {
Q_UNUSED(menu);
QApplication *self = static_cast<QApplication *>(data);
self->quit();
}
void ShowUnityAppIndicator()
{
AppIndicator *indicator;
GtkWidget *menu, *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(item, "activate",
G_CALLBACK(quitIndicator), qApp); // We cannot connect
// gtk signal and qt slot so we need to create proxy
// function later on, we pass qApp pointer as an argument.
// This is useful when we need to call signals on "this"
//object so external function can access current object
gtk_widget_show(item);
indicator = app_indicator_new(
"unique-application-name",
"indicator-messages",
APP_INDICATOR_CATEGORY_APPLICATION_STATUS
);
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_ACTIVE);
app_indicator_set_menu(indicator, GTK_MENU(menu));
}
void ShowQtSysTray(QApplication* app, QDialog* dialog)
{
Q_INIT_RESOURCE(resources);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
QMessageBox::critical(0, QObject::tr("Systray"),
QObject::tr("I couldn't detect any system tray "
"on this system."));
}
QApplication::setQuitOnLastWindowClosed(false);
QSystemTrayIcon* trayIcon = new QSystemTrayIcon(dialog);
QAction* Action = new QAction("hello", dialog);
QMenu* trayIconMenu = new QMenu(dialog);
trayIconMenu->addAction("Quit", app, SLOT(quit()));
trayIconMenu->addAction(Action);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->setIcon(QIcon (":/icons/Icons/accept.png"));
trayIcon->show();
trayIcon->showMessage("Title","Message");
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
//Determine the desktop type
QString desktop;
bool is_unity;
desktop = getenv("XDG_CURRENT_DESKTOP");
is_unity = (desktop.toLower() == "unity");
if(is_unity)
{
ShowUnityAppIndicator();
}
else
{
//Show the SystemTrayIcon the Qt way
ShowQtSysTray(&a, &w);
}
// w.show();
return a.exec();
}

Linking Qt DLL to Qt App - unresolved references

I've just installed Qt 4.7.4 and trying to make a simple Qt App that uses Qt DLL. I added export/import in a class in DLL through ifdef as usual but when compiling App I het unresolved references. I also set that App depends on the DLL.
Here are the main files:
Lib.pro
QT -= gui
TARGET = Lib
TEMPLATE = lib
DEFINES += LIB_LIBRARY
SOURCES += lib.cpp
HEADERS += lib.h\
Lib_global.h
symbian {
MMP_RULES += EXPORTUNFROZEN
TARGET.UID3 = 0xE10C4E25
TARGET.CAPABILITY =
TARGET.EPOCALLOWDLLDATA = 1
addFiles.sources = Lib.dll
addFiles.path = !:/sys/bin
DEPLOYMENT += addFiles
}
unix:!symbian {
maemo5 {
target.path = /opt/usr/lib
} else {
target.path = /usr/lib
}
INSTALLS += target
}
App.pro
QT += core gui
TARGET = App
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
lib.h
#ifndef LIB_H
#define LIB_H
#include "Lib_global.h"
#include <QString>
class LIBSHARED_EXPORT Lib {
public:
Lib();
~Lib();
QString Hello(QString a);
};
#endif // LIB_H
Lib_global.h
#ifndef LIB_GLOBAL_H
#define LIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(LIB_LIBRARY)
# define LIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define LIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // LIB_GLOBAL_H
What's wrong with this code? Why is it unresolved reference?
In App I just include "../Lib/lib.h" and try to use the class.
What looks to be missing is the link between your application and your dynamic library.
I usually do something like this for my desktop (linux) apps:
INCLUDEPATH += ./include
LIBS += -L./lib -lLib
Where:
INCLUDEPATH defines the path to where your shared library .h files are located.
LIBS defines the path to where your built library is.
You can find the relevant documentation here: QMake - Declaring Other Libraries
Updated:
I was able to build the project (Linux Qt v4.7.4) and link to the library using the code you posted. I will try to clarify as my response may not be entirely clear.
The INCLUDEPATH and LIBS variables must be added to the App.pro file.
For the linker to properly find the library the paths must be adjusted to the paths you are using for your project:
LIBS += -L PATH -l LIBNAME
Supposing your folder structure is similar to the following:
Project
|_ Lib (your sharded library project files)
|_ App (your application project files)
You would adjust the variables like so:
INCLUDEPATH += ../Lib
LIBS += -L../Lib -lLib
Note that you link differently depending on your platform, you can do something like this to cover Windows and Linux:
unix {
INCLUDEPATH += ../Lib
LIBS += -L../Lib -lLib
}
win32 {
INCLUDEPATH += ../Lib
LIBS += ../Lib.lib
}

Resources