2012-10-06 120 views
0

我正在構建一個Qt應用程序。儘管之前我已經編寫了很多GUI,而且框架本身沒有出現問題,但我從來沒有編寫過任何(C#.NET應用程序之外的)有能力加載插件的東西。我試圖構建的項目有插件作爲它的一個組成部分,我認爲Qt框架看起來不錯,因爲它幾乎是普遍跨平臺的,並且似乎有一個非常好的插件系統。QPluginLoader實例總是返回null

我的問題是這樣的:我似乎無法得到QPluginLoader.instance()方法來返回除空值之外的任何內容。

從我的閱讀中,這是因爲它找不到插件。我想我可能忘記了做些什麼,但是我可以在實際編寫插件時找到很少的文檔(有一些例子,但它們並不令人難以置信地詳細)。有很多加載插件的例子,我認爲我這樣做是正確的,但我還沒有真正找到一個實際製作插件的例子。

這是我做了什麼:

使用Qt的造物主我已經創建了兩個項目:一個窗口應用程序假裝它是我的插件接收應用程序和共享庫項目冒充插件

在我的窗口應用程序,我有一個頭文件如下:

#ifndef PLUGININTERFACE_H 
#define PLUGININTERFACE_H 

#include <QtPlugin> 

class QStringList; 

class PluginInterface 
{ 
public: 
    virtual ~PluginInterface() {}; 

    virtual QStringList messages() const = 0; 
}; 

Q_DECLARE_INTERFACE(PluginInterface, 
        "com.kevincuzner.LearningPlugins.PluginInterface/1.0") 

#endif // PLUGININTERFACE_H 

在我的共享庫的應用程序,我創建了一個名爲ATestPlugin類(這也是該項目的目標值):

#ifndef ATESTPLUGIN_H 
#define ATESTPLUGIN_H 

#include "ATestPlugin_global.h" 
#include "../LearningPlugins/PluginInterface.h" 

#include <QStringList> 


class ATESTPLUGINSHARED_EXPORT ATestPlugin : public PluginInterface, public QObject 
{ 

    Q_OBJECT 
    Q_INTERFACES(PluginInterface) 

public: 
    ATestPlugin(); 

    virtual QStringList messages() const 
    { 
     //this part is actually defined in the .cpp file, but I don't feel like pasting that here 
     QStringList ret; 
     ret << "foo" << "bar" << "noms" << "Hello"; 

     return ret; 
    } 
}; 

#endif // ATESTPLUGIN_H 

在我在我做了以下(&W¯¯點到主窗口)的主要方法放置Q_EXPORT_PLUGIN2(ATestPlugin, ATestPlugin)

然後在我的main.cpp文件ATestPlugin.cpp文件的末尾:

QString text = QFileDialog::getOpenFileName(&w, "Get a file"); 
QPluginLoader loader(text); 
QObject* plugin = loader.instance(); 
if (plugin) 
{ 
    QMessageBox msgBox; 
    msgBox.setText(text); 
    msgBox.exec(); 
} 

當我運行該程序並從彈出的文件對話框的庫項目的構建目錄中選擇libATestPlugin.so時,我看不到任何消息框,表示* plugin爲空。以前我總是彈出消息框並顯示選定的文件名,所以我知道該部分正在工作。

有沒有人有任何想法,我需要做什麼使我的插件可見QPluginLoader?

+0

可能不是解決方案,但是我發現Qt可能很有趣,因爲在ATestPlugin的類繼承聲明中沒有首先使用'QObject'。 – cmannett85

+0

您是否檢查插件是否在正確的位置? – Synxis

回答

0

經過進一步的實驗,我設法讓插件加載。我對此感到羞怯,但這是RTFM的經典案例。

echo plugin tutorial(我還沒有找到,直到後,我張貼的問題)有一些修改過的.pro文件來進行在庫,使其正確聲明插件:

TARGET = ATestPlugin必須更改爲TARGET = $$qtLibraryTarget(ATestPlugin)。在做出這個改變之後,我的消息箱在上面的程序彈出,之後當我運行qobject_cast< PluginInterface* >(plugin),然後問跑PluginInterface->messages()我得到了在單獨的類中實現的列表。另外,我確實改變了繼承順序,把QObject放在第一位,因爲它的工作方式我可能會保留它(儘管我不知道它是否有所不同)。

+0

我目前正在用Qt構建一個基於插件的應用程序,而我從來沒有見過'$$ qtLibraryTarget(..)'。如果你有時間,知道是否恢復該行可以停止它再次工作會很有趣。 – cmannett85

1

它沒有爲我工作。將以前的TARGET更改爲$$ qtLibraryTarget(...),以確保在不同平臺上構建時的正確擴展。

我有與QPluginLoader相同的問題。用幾句話來解釋它:我創建插件庫,讓我們說lib1.dll,它使用lib2.dll中的一些東西。在我的應用程序中,我嘗試通過QPluginLoader加載lib1。

QPluginLoader loader(adaptersDir.absoluteFilePath(fileName)); 
AdapterInterface* adapterIface = qobject_cast<AdapterInterface*>(loader.instance()); 

在這種情況下loader.instance()返回0的解決辦法是lib2.dll複製到應用程序文件夾,因爲應用程序使用它的適當的負載插件lib1內。