QT外掛開發方式
建立一個QT的庫專案,刪除自動生成的.h和.cpp檔案,新增一個介面定義.h檔案和一個介面實現類(一個.h一個.cpp).程式碼如下:
1.介面檔案原始碼
#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H
#include <QString>
class EchoInterface
{
public:
virtual ~EchoInterface() {}
virtual QString echo(const QString &message) = 0;
};
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(EchoInterface, "com.hollysys.plugin.EchoIntrface/1.0");
QT_END_NAMESPACE
#endif
2.介面實現類標頭檔案
#ifndef PLUGIN_H
#define PLUGIN_H
//#include "plugin_global.h"
#include <QObject>
#include "plugininterface.h"
class Plugin : public QObject, EchoInterface
{
Q_OBJECT
Q_INTERFACES(EchoInterface)
public:
Plugin();
~Plugin();
public:
QString echo(const QString &message);
};
#endif // PLUGIN_H
3.介面實現類cpp檔案
#include "plugin.h"
#include <QtGui>
Plugin::Plugin()
{
}
Plugin::~Plugin()
{
}
QString Plugin::echo(const QString &message)
{
return message;
}
Q_EXPORT_PLUGIN2("echoPlugin", Plugin);
編譯生成dll格式的外掛.這裡可能會遇到LNK2001錯誤,因為外掛介面定義依賴於QT的元資料,而在程式碼中手動新增Q_OBJECT巨集後,編譯器不會自動為我們生成moc_XXXX.cpp檔案,因此需要使用命令列生成moc元資料檔案:cmd-->cd 原始碼所在命令 -->moc -o moc_XXXX.cpp XXXX.h.這樣就可以手動創建出moc元資料檔案,解決LNK2001編譯錯誤.
建立一個GUI測試專案,程式碼如下:
#include "test.h"
#include <QtGui>
#include <QMessageBox>
#include <QDir>
Test::Test(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QObject::connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(ButtonClicked()));
loadPlugin();
}
Test::~Test()
{
}
bool Test::loadPlugin()
{
QDir pluginsDir(qApp->applicationDirPath());
foreach (QString filename, pluginsDir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(filename));
QObject *plugin = pluginLoader.instance();
if(plugin)
{
echoInterface = qobject_cast<EchoInterface *>(plugin);//echoInterface是成員變數
if(echoInterface)
return true;
}
}
}
void Test::ButtonClicked()
{
QString plugin = ui.lineEdit->text();
QMessageBox::information(NULL, "", echoInterface->echo(plugin));
}
分析程式碼可見,這裡對所有與exe檔案同目錄的檔案嘗試載入外掛,如果載入成功則返回.程式碼實現非常簡潔.在正式開發中可將已載入的外掛介面存放在列表中,在需要的時候依次呼叫即可.
另外如果想獲取外掛中類定義的元資料,可以使外掛介面類從QObject繼承,並使用Q_CLASSINFO巨集新增鍵值對,如Q_CLASSINFO("Author**", "Henreash**").並從主程式中使用外掛物件元資料獲取這些鍵值對:
const QMetaObject *mo = echoInterface->metaObject();
for(int i = 0; i < mo->classInfoCount(); i++)
{
qDebug() << mo->classInfo(i).name() << mo->classInfo(i).value();
}
使用這個機制可以在定義外掛類的時候向主程式傳遞一些特殊資訊.
測試發現,如果在外掛介面類中定義一個靜態變數,那麼這個靜態變數在外掛中的地址和在主程式中的地址是不相同的.
FROM: http://blog.csdn.net/henreash/article/details/7264489