继续朝QtRSSReader前进,
今天写了个简单的记XML日志的Qt插件。
从9点摸索到11点,花了两个小时,跌跌撞撞总算搞定了,把这其中曲折记下来,希望大家不要重蹈我的覆辙。
首先需要一个简单的exe调用插件,我的代码如下: #include <QApplication>
#include <QTextCodec>
#include <QLabel>
#include <QPluginLoader>
#include <QObject>
//---------------------
#include <QMessageBox>
#include "LogInterface.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QLabel label("Demo LogInterface");
label.show();
QPluginLoader pluginLoader(QObject::tr("/media/工作/个人代码库/练习/QT练习/15.QtPlugin/plugin/liblogWriter.so"));
QObject *plugin =
pluginLoader.instance(); QMessageBox::information(0, "", QObject::tr("装载成功?%1").arg(pluginLoader.isLoaded()?QObject::tr("装载成功"):pluginLoader.errorString())); if (plugin)
{
QMessageBox::information(0, "", "plugin != NULL");
LogInterface * logInterface = qobject_cast<LogInterface *>(plugin);
if (logInterface)
{
QMessageBox::information(0, "", "logInterface != NULL");
logInterface->writeLog("Demo Message", "Demo Date", "Demo Source",
"Demo User", LogInterface::llTrace);
}
}
pluginLoader.unload();
return app.exec();
}
这个比较简单,主要就是QPluginLoader的使用,
比较关键一点,大概就是isLoad需要在
pluginLoader.instance()之后进行判断,
构造的虽然传递了插件的路径,但并不进行Load。进行isLoad判断自然无效了。
接下来是共享的接口文件声明,在C++中就是纯虚类的头文件,代码如下: #ifndef LOGINTERFACE_H
#define LOGINTERFACE_H
#include <QString>
class LogInterface
{
public:
enum LogLevel{llTrace, llDebug, llInformation, llError};
virtual void writeLog(const QString aLogMessage, const QString aLogDate,
const QString aLogSource, const QString aLogUser,
const LogLevel aLogLevel)
= 0;
/*作为接口必须是虚函数,否则会报类似QLibrary::load_sys: Cannot load /home/foo/src/demo/plugins/libmyPlugin.so (/home/foo/src/demo/plugins/libmyPlugin.so: undefined symbol: _ZTI15PluginInterface)的错误*/};
Q_DECLARE_INTERFACE(LogInterface, "se.thelins.pluginDemo.LogInterface/0.1"); #endif
这里的
Q_DECLARE_INTERFACE需要特别留意,开始我不明白什么意思,随编拷贝了一份,把LogInterface替换了。后面才知道这段字符串分成四部分
公司名或者其他什么东西 ---应该是个描述,不确定
pluginDemo 创建该接口的应用,这个名字应该是应用程序的taget名字
LogInterface 接口名称
0.1 版本号
插件的实现部分着实郁闷了我一把。代码如下:
头文件依葫芦画瓢,比较简单。 #ifndef LOGWRITER_H
#define LOGWRITER_H
#include <QObject>
#include <QString>
#include <QDomDocument>
#include "LogInterface.h"
class LogWriter: public QObject, public LogInterface
{
Q_OBJECT Q_INTERFACES(LogInterface) public:
void writeLog(const QString aLogMessage, const QString aLogDate,
const QString aLogSource, const QString aLogUser,
const LogLevel aLogLevel);
};
#endif
在这里,我想Q_OBJECT没什么用处吧,主要是为了moc带signal/slot的头文件
实现部分我落下了一个东西,导致后面测试过程中,报无效的插件 #include <QDomDocument>
#include <QDomElement>
#include <QFile>
#include <QtPlugin> //-------------------------
#include <QMessageBox>
#include "logWriter.h"
void LogWriter::writeLog(const QString aLogMessage, const QString aLogDate,
const QString aLogSource, const QString aLogUser,
const LogLevel aLogLevel)
{
QDomDocument doc;
QDomElement root, log;
QFile file("../log.xml");
if (!file.open(QIODevice::ReadOnly))
{
root = doc.createElement("Logs");
doc.appendChild(root);
}
else
{
doc.setContent(&file);
root = doc.documentElement();
}
//file.close();
log = doc.createElement("Log");
log.setAttribute("Message", aLogMessage);
log.setAttribute("Date", aLogDate);
log.setAttribute("Source", aLogSource);
log.setAttribute("User", aLogUser);
log.setAttribute("Level", int(aLogLevel));
root.appendChild(log);
file.seek(0);
file.write(doc.toByteArray());
file.close();
}
Q_EXPORT_PLUGIN2(logwriter, LogWriter)//包含在<QtPlugin>中
只能怪我看代码不细致,没有看到代码最后一行有
Q_EXPORT_PLUGIN2 --------------------------
代码就是这些,插件的pro文件也需要照样子修改。我的pro文件如下
TEMPLATE = lib CONFIG += plugin debug#这里我不是很明白CONFIG还能有些什么参数
VERSION = 1.0.0 #照抄,不知道会不会和上面的0.1关联
TARGET = logWriter #目标
DEPENDPATH += .
INCLUDEPATH += .. #声明文件在上级目录
# Input
HEADERS += logWriter.h
SOURCES += logWriter.cpp
target.path += .
INSTALLS += target #不了解,不确定不添加这一段能不能用
主程序源代码
application.tar.gz (3 K) 下载次数:126 插件源代码
plugin.tar.gz (3 K) 下载次数:116 [ 此贴被wvins在2008-11-27 09:56重新编辑 ]