From: http://blog.csdn.net/henreash/article/details/7264489@import url(http://m.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
創建一個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();
}
使用這個機制可以在定義插件類的時候向主程序傳遞一些特殊信息.
測試發現,如果在插件接口類中定義一個靜態變量,那么這個靜態變量在插件中的地址和在主程序中的地址是不相同的.