一、簡介
服務追蹤:如果想在B插件里使用A服務,可以專門寫一個類繼承ctkServiceTracker,在這個類里完成對A服務的底層操作,然后在B插件里通過這個類提供的接口來使用回收A服務。
注意ctkServiceTracker和A服務應該是一起的,這里有點像服務工廠。優點就是獲取服務的代碼簡單,不用各種判斷空指針【實際使用中感覺缺點大於優點】
二、新建A服務
這里直接使用以前服務工廠里的那個打印服務【通過服務工廠訪問服務】:https://www.cnblogs.com/judes/p/13237502.html
三、新建ctkServiceTracker子類Tracker
主要實現以下三個接口,注意ctkServiceTracker是一個模板類,需要指明主要追蹤的服務類名
tracker.h
#ifndef TRACKER_H #define TRACKER_H #include "ctkServiceTracker.h" #include "absprintserver.h" #include "ctkPluginContext.h" class Tracker : public ctkServiceTracker<AbsPrintServer*> { public: Tracker(ctkPluginContext* context); protected: AbsPrintServer* addingService(const ctkServiceReference& reference) override; void modifiedService(const ctkServiceReference& reference, AbsPrintServer* service) override; void removedService(const ctkServiceReference& reference, AbsPrintServer* service) override; private: ctkPluginContext* context; }; #endif // TRACKER_H
tracker.cpp
#include "tracker.h" Tracker::Tracker(ctkPluginContext *context) : ctkServiceTracker<AbsPrintServer*> (context) { } AbsPrintServer *Tracker::addingService(const ctkServiceReference &reference) { AbsPrintServer* service = static_cast<AbsPrintServer*>(ctkServiceTracker::addingService(reference)); return service; } void Tracker::modifiedService(const ctkServiceReference &reference, AbsPrintServer* service) { ctkServiceTracker::modifiedService(reference,service); } void Tracker::removedService(const ctkServiceReference &reference, AbsPrintServer* service) { ctkServiceTracker::removedService(reference,service); }
關於這個追蹤類,什么時候建立呢?這個問題繞了我很久,經過思考應該有如下幾種方式。
1、可以在封裝A服務的時候就建立,作為一種工具向外提供,但是不應該被編譯進插件中,它並不是插件的功能而是訪問插件的工具;
2、也可以在B插件中建立,完全和A服務獨立開,作為訪問A服務的一種手段;
3、單獨建立一個空工程,為項目中的所有服務建立對應的追蹤類,然后放在同一個文件夾中,其他想要的自己使用就行。
但是要注意:B插件如果想要使用A服務,需要tracker.h、tracker.cpp、A服務的接口類。
四、新建B插件工程
1、接口類
abslogtracker.h
#ifndef ABSLOGTRACKER_H #define ABSLOGTRACKER_H #include <QObject> class AbsLogTracker{ public: virtual ~AbsLogTracker(){} virtual void log(QString) = 0; }; Q_DECLARE_INTERFACE(AbsLogTracker,"judesmorning.zxy.AbsLogTracker") #endif // ABSLOGTRACKER_H
2、實現類
imlog.h
#ifndef IMLOG_H #define IMLOG_H #include <QObject> #include "abslogtracker.h" #include "tracker.h" class ImLog : public QObject, public AbsLogTracker { Q_OBJECT Q_INTERFACES(AbsLogTracker) public: ImLog(Tracker* tracker); void log(QString info) override; private: Tracker* tracker; }; #endif // IMLOG_H
imlog.cpp
#include "imlog.h" #include <QDebug> ImLog::ImLog(Tracker* tracker) : tracker(tracker) { } void ImLog::log(QString info) { AbsPrintServer* service = static_cast<AbsPrintServer*>(tracker->getService()); if (service != Q_NULLPTR) { service->print("test plugin with tracker:"+info); } else { qDebug()<<"get AbsPrintServer from tracker failed"; } }
因為真正使用到A服務的地方就是B插件的實現類里,所以通過構造函數把tracker給傳進去。這里的tracker是在激活類里new的,因為context是從實現類里傳進來的,根據這個思路也可把context傳到B的實現類里,再在實現類里new出tracker
3、激活類
activator.h
#ifndef ACTIVATOR_H #define ACTIVATOR_H #include <QObject> #include "tracker.h" #include "imlog.h" #include "ctkPluginActivator.h" #include "ctkPluginContext.h" class Activator : public QObject , public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) Q_PLUGIN_METADATA(IID "AbsLogTracker") public: Activator(); void start(ctkPluginContext* context) override; void stop(ctkPluginContext* context)override; private: QScopedPointer<Tracker> p_tracker; QScopedPointer<ImLog> p_plugin; ctkServiceRegistration m_registration; }; #endif // ACTIVATOR_H
activator.cpp
#include "activator.h" Activator::Activator() { } void Activator::start(ctkPluginContext *context) { p_tracker.reset(new Tracker(context)); p_tracker->open(); p_plugin.reset(new ImLog(p_tracker.data())); m_registration = context->registerService<AbsLogTracker>(p_plugin.data()); } void Activator::stop(ctkPluginContext *context) { Q_UNUSED(context); m_registration.unregister(); p_tracker->close(); p_tracker.reset(nullptr); p_plugin.reset(nullptr); }
ps:
1、在B插件使用A服務的時候,一定要把tracker源文件加入到B插件工程中去,即.pro里要有它們,不能只include,不然會報錯