如何在 Qt C++ 中动态创建和加载库
How do I create and load lib dynamically in Qt C++
如 https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application 所述,我想创建 dll (Windows 10) 并使用 QLibrary 作为插件动态加载它。
在 Dependency Walker 中,我看到可以加载 exports 和 dll。但是 resolve 总是给我 0。我在网络上尝试了几个例子和 hinds,但没有成功。我做错了什么?
.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
TEMPLATE = lib
HEADERS += eurolite_dmx512_pro_mk2.h \
Eurolite_DMX512_Pro_MK2_global.h
SOURCES += eurolite_dmx512_pro_mk2.cpp
DEFINES += EUROLITE_DMX512_PRO_MK2_LIBRARY
global.h
#ifndef EUROLITE_DMX512_PRO_MK2_GLOBAL_H
#define EUROLITE_DMX512_PRO_MK2_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(EUROLITE_DMX512_PRO_MK2_LIBRARY)
# define EUROLITE_DMX512_PRO_MK2 Q_DECL_EXPORT
#else
# define EUROLITE_DMX512_PRO_MK2 Q_DECL_IMPORT
#endif
#endif // EUROLITE_DMX512_PRO_MK2_GLOBAL_H
.h
#ifndef SHARED_H
#define SHARED_H
#include "Eurolite_DMX512_Pro_MK2_global.h"
#include <QDebug>
class Device
{
public:
Device();
void Testdll() {qDebug("OK");}
};
extern "C" EUROLITE_DMX512_PRO_MK2 int getVersion();
extern "C" EUROLITE_DMX512_PRO_MK2 QWidget *createWidget1();
int EUROLITE_DMX512_PRO_MK2 libStart(void)
{
Device device;
return 0;
}
#endif // SHARED_H
.cpp
#include <QWidget>
#include "eurolite_dmx512_pro_mk2.h"
Device::Device() {}
int getVersion()
{
return 3;
}
QWidget *createWidget1()
{
QWidget *widget = new QWidget();
widget->resize(100, 100);
return widget;
}
plugintest.c++
#include "dmxservice.h"
#include <QApplication>
#include <QDebug>
#include <QLibrary>
#include <QMessageBox>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
bool dmxLibAktiv = false;
QLibrary dmxlib;
QMessageBox msgBox;
QFile file(QCoreApplication::applicationDirPath()+"/devices/Eurolite_DMX512_Pro_MK2.dll");
if(file.exists()==true)
{
QLibrary dmxlib(QCoreApplication::applicationDirPath()+"/devices/Eurolite_DMX512_Pro_MK2.dll");
if(dmxlib.load()==true)
{
dmxLibAktiv = dmxlib.isLoaded();
msgBox.setText("DLL loaded!\n");
msgBox.exec();
}
else
{
msgBox.setText("DLL not loaded!\n"+dmxlib.errorString());
msgBox.exec();
}
}
else
{
msgBox.setText("DLL not found '"+QCoreApplication::applicationDirPath()+"'!\n");
msgBox.exec();
}
if (dmxLibAktiv) {
typedef QWidget *(*CreateWidgetFunction)();
CreateWidgetFunction cwf = CreateWidgetFunction(dmxlib.resolve("createWidget1"));
if (cwf) {
QWidget *widget = cwf();
if (widget)
widget->show();
} else {
qDebug() << "Could not show widget from the loaded library";
}
}
DmxService w;
w.show();
return a.exec();
}
您在 if (file.exists())
分支中创建了本地 QLibrary dmxlib(...);
。所以外部 dmxlib
实例永远不会被初始化。
ADDED:不要在if
块中重新声明变量,改用setFileName()
:
QLibrary dmxlib;
...
if (file.exists()) {
dmxlib.setFileName(QCoreApplication::applicationDirPath()+"/devices/Eurolite_DMX512_Pro_MK2.dll");
if (dmxlib.load())
....
}
// ... use dmxlib
如 https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_application 所述,我想创建 dll (Windows 10) 并使用 QLibrary 作为插件动态加载它。
在 Dependency Walker 中,我看到可以加载 exports 和 dll。但是 resolve 总是给我 0。我在网络上尝试了几个例子和 hinds,但没有成功。我做错了什么?
.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
TEMPLATE = lib
HEADERS += eurolite_dmx512_pro_mk2.h \
Eurolite_DMX512_Pro_MK2_global.h
SOURCES += eurolite_dmx512_pro_mk2.cpp
DEFINES += EUROLITE_DMX512_PRO_MK2_LIBRARY
global.h
#ifndef EUROLITE_DMX512_PRO_MK2_GLOBAL_H
#define EUROLITE_DMX512_PRO_MK2_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(EUROLITE_DMX512_PRO_MK2_LIBRARY)
# define EUROLITE_DMX512_PRO_MK2 Q_DECL_EXPORT
#else
# define EUROLITE_DMX512_PRO_MK2 Q_DECL_IMPORT
#endif
#endif // EUROLITE_DMX512_PRO_MK2_GLOBAL_H
.h
#ifndef SHARED_H
#define SHARED_H
#include "Eurolite_DMX512_Pro_MK2_global.h"
#include <QDebug>
class Device
{
public:
Device();
void Testdll() {qDebug("OK");}
};
extern "C" EUROLITE_DMX512_PRO_MK2 int getVersion();
extern "C" EUROLITE_DMX512_PRO_MK2 QWidget *createWidget1();
int EUROLITE_DMX512_PRO_MK2 libStart(void)
{
Device device;
return 0;
}
#endif // SHARED_H
.cpp
#include <QWidget>
#include "eurolite_dmx512_pro_mk2.h"
Device::Device() {}
int getVersion()
{
return 3;
}
QWidget *createWidget1()
{
QWidget *widget = new QWidget();
widget->resize(100, 100);
return widget;
}
plugintest.c++
#include "dmxservice.h"
#include <QApplication>
#include <QDebug>
#include <QLibrary>
#include <QMessageBox>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
bool dmxLibAktiv = false;
QLibrary dmxlib;
QMessageBox msgBox;
QFile file(QCoreApplication::applicationDirPath()+"/devices/Eurolite_DMX512_Pro_MK2.dll");
if(file.exists()==true)
{
QLibrary dmxlib(QCoreApplication::applicationDirPath()+"/devices/Eurolite_DMX512_Pro_MK2.dll");
if(dmxlib.load()==true)
{
dmxLibAktiv = dmxlib.isLoaded();
msgBox.setText("DLL loaded!\n");
msgBox.exec();
}
else
{
msgBox.setText("DLL not loaded!\n"+dmxlib.errorString());
msgBox.exec();
}
}
else
{
msgBox.setText("DLL not found '"+QCoreApplication::applicationDirPath()+"'!\n");
msgBox.exec();
}
if (dmxLibAktiv) {
typedef QWidget *(*CreateWidgetFunction)();
CreateWidgetFunction cwf = CreateWidgetFunction(dmxlib.resolve("createWidget1"));
if (cwf) {
QWidget *widget = cwf();
if (widget)
widget->show();
} else {
qDebug() << "Could not show widget from the loaded library";
}
}
DmxService w;
w.show();
return a.exec();
}
您在 if (file.exists())
分支中创建了本地 QLibrary dmxlib(...);
。所以外部 dmxlib
实例永远不会被初始化。
ADDED:不要在if
块中重新声明变量,改用setFileName()
:
QLibrary dmxlib;
...
if (file.exists()) {
dmxlib.setFileName(QCoreApplication::applicationDirPath()+"/devices/Eurolite_DMX512_Pro_MK2.dll");
if (dmxlib.load())
....
}
// ... use dmxlib