Max*_*nko 5 qt multiple-instances
首先对不起我的英语
我已经使用 Qt 开发了财务打印机的驱动程序。驱动程序细节是通过 RS232 在 PC 和设备之间进行通信。存储在共享对象(Qt 插件)中的驱动程序和服务器通过 QPluginLoader 执行其加载。
所以,关于我的问题......当我使用一个设备和一个驱动程序实例时一切正常,但是当我连接许多设备(例如 3 个)时,只有最后加载的设备工作。我已经完成了许多代码检查,读取了许多日志数据转储,设备和端口命名没有错误,但是如果我使用命令寻址第一个设备 - 2 个左侧设备接收相同的命令(根据日志条目)并且仅最后加载设备执行命令执行。
例如:我从我的服务器向设备 1 发送 PrintReceipt 命令,在设备 1 的日志文件中我看到条目:PrintReceipt,在设备 2 的日志文件中我看到条目:PrintReceipt、:PrintReceipt 和设备 3 的日志文件我看到3个相同的条目。所以,当我看到我的问题时 - QPluginLoader 为第一个加载的设备创建一个驱动程序实例,然后,当我尝试将驱动程序加载到第二个设备时 - QPluginLoader 创建新实例并替换最近创建的第一个设备的驱动程序,依此类推每个设备. 因此,至少,对于许多设备,我只有一个驱动程序(插件)实例,并且我的应用程序逻辑崩溃了。
我的问题是:如何使用 QPluginLoader 在 Qt 中创建同一个插件的多个实例?下面列出了我的驱动程序界面和加载代码。
class IPrinterDriver : public QObject
{
public:
// Printer driver initialization
virtual bool Init(QextSerialPort* port, const QString& deviceID) = 0;
// Driver identify name
virtual QString GetName() = 0;
// Gets current device state
virtual DeviceStates GetState() = 0;
// Gets device info and state test
virtual QString DeviceInfo() = 0;
// Set print mode to specified
virtual bool SetPrintMode(PrintModes mode) = 0;
// Get current print mode
virtual PrintModes PrintMode() const = 0;
// Sets device password from configuration
virtual void SetDevicePasswords(int operatorPassword, int adminPassword) = 0;
// Sets non-fiscal permissoin to device
virtual void SetNonFiscalModePermission(bool allowed) = 0;
// Gets device operator password
virtual int GetOperatorPassword() const = 0;
// Gets device administrator password
virtual int GetAdministratorPassword() const = 0;
// Gets non-fiscal mode permission
virtual bool GetNonFiscalModePermission() const = 0;
// Payment transaction
virtual bool PaymentTransaction(PaymentItem& item) = 0;
// Query device for X-Report
virtual bool GetXReport() = 0;
// Encashment transaction (Z-Report)
virtual bool Encash(bool fromBuffer) = 0;
// Print transaction
virtual bool Print(QString& text) = 0;
// Performs fiscal sale at device and returns receipt data
virtual FiscalReceiptData FPSSale(int requestID, int amount) = 0;
// Gets last fiscal receipt data
virtual FiscalReceiptData GetLastReceiptData() = 0;
// Gets serial port assigned to device
virtual QextSerialPort* GetDevicePort() = 0;
signals:
// Emits when device logging needed
virtual void DeviceLoggingNeeded(LogEntry entry, const QString& deviceID) = 0;
};
Q_DECLARE_INTERFACE(IPrinterDriver, "InfSys.Devices.IPrinterDriver/1.0")
Run Code Online (Sandbox Code Playgroud)
和驱动加载方法:
// Performs loading specified driver for device at specified port
IPrinterDriver* PrintSystem::LoadDriver(PortConfiguration portConfig, const QString& driverName, const QString& adminPassword, const QString& operPassword, const QString& deviceID)
{
IPrinterDriver* result = NULL;
// Prepare plugin loader
QDir driversDir(_driversPath);
QStringList filesMask;
filesMask << tr("libdriver.%1.*").arg(driverName);
driversDir.setNameFilters(filesMask);
QStringList driversFiles = driversDir.entryList(QDir::Files);
// Load plugin with specified driver
foreach(QString driverFile, driversFiles)
{
// Load current driver;
QString driverFileName = driversDir.absoluteFilePath(driverFile);
QPluginLoader driversLoader(driverFileName);
// Try to init driver
QObject *driverObject = driversLoader.instance();
if (driverObject)
{
result = qobject_cast<IPrinterDriver *>(driverObject);
if (result && (result->GetName() == driverName))
{
QextSerialPort* devicePort = ConfigureSerialPort(portConfig);
if (devicePort == NULL)
{
driversLoader.unload();
return NULL;
}
// Init device
result->SetDevicePasswords(operPassword.toInt(), adminPassword.toInt());
result->SetNonFiscalModePermission(false);
result->SetPrintMode(Fiscal);
connect(result, SIGNAL(DeviceLoggingNeeded(LogEntry,QString)), App->LoggingModule, SLOT(OnDeviceLoggingNeeded(LogEntry,QString)), Qt::QueuedConnection);
bool initResult = result->Init(devicePort, deviceID);
if (!initResult)
{
driversLoader.unload();
return NULL;
}
}
else
driversLoader.unload();
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我在自己的项目中研究这个问题已经有一段时间了。我相信没有任何方法可以直接执行此操作 - QPluginLoader 正在按设计工作。
到目前为止,我提出的解决这个问题的最直接的方法是使主要插件接口函数成为您真正想要的对象的工厂。
在下面的示例中,我真正想要的是多个 IPlaybackDataSource 对象。所以我创建了一个插件实现的工厂接口。然后,该插件返回任意数量的我想要的类型的对象。
IPlaybackDataSource.h:
#include <QSharedPointer>
class IPlaybackDataSource {
public:
virtual bool open()=0;
};
// This is the interface that the plugin will implement
class IPlaybackDSFactory {
public:
virtual QSharedPointer<IPlaybackDataSource> newDataSource()=0;
};
Q_DECLARE_INTERFACE(IPlaybackDSFactory,
"com.moberg.DeviceSimulators.IPlaybackDSFactory/1.0")
Run Code Online (Sandbox Code Playgroud)
翻译文件.h:
#include <QtGui>
#include "TranFile_global.h"
#include "IPlaybackDataSource.h"
class TRANFILESHARED_EXPORT TranFile : public QObject, public IPlaybackDSFactory
{
Q_OBJECT
Q_INTERFACES(IPlaybackDSFactory)
public:
TranFile();
~TranFile();
virtual QSharedPointer<IPlaybackDataSource> newDataSource();
};
Run Code Online (Sandbox Code Playgroud)
翻译文件.cpp:
#include "TranFile.h"
Q_EXPORT_PLUGIN2(IPlaybackDSFactory, TranFile );
#include <QtCore>
#include <QDebug>
TranFile::TranFile(): QObject(), IPlaybackDSFactory() {}
TranFile::~TranFile() {}
QSharedPointer<IPlaybackDataSource> TranFile::newDataSource() {
return QSharedPointer<IPlaybackDataSource>();
}
Run Code Online (Sandbox Code Playgroud)