2013-07-24 81 views
2

首先對不起我的英文如何使用QPluginLoader在Qt中創建同一個插件的多個實例?

我開發了使用Qt的財務打印機驅動程序。驅動程序細節是通過RS232在PC和設備之間進行通信。存儲在共享對象(Qt插件)中的驅動程序和服務器通過QPluginLoader執行加載。

因此,關於我的問題...當我使用一個設備和一個驅動程序實例都工作正常,但是當我附加很多設備(例如3)時,只有最後加載的設備工作。我已經完成了許多代碼檢查,讀取了許多日誌數據轉儲,設備和端口命名沒有錯誤,但是如果我使用命令來處理第一個設備 - 兩個左側設備接收到相同的命令(根據日誌條目)並且只有最後一個加載設備執行命令執行。

例如:從我的服務器我發送PrintReceipt命令到設備1,在設備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") 

和驅動程序加載方法:

// 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; 
} 

回答

0

我一直在尋找這個問題,而現在我自己的項目。我相信沒有辦法直接做到這一點 - 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") 

TranFile.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(); 
}; 

TranFile.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>(); 
} 
相關問題