X3架構應用

logens發表於2015-12-29

看了許久,都沒有理解這個架構,索性將之鋪陳紙上,但願能稍微入門,此博文轉為轉載,不是原創。

X3外掛基礎模組是X3外掛框架的最底層獨立模組,用於形成其他外掛模組。X3外掛框架的設計目標是彙集各種常用的輕量級C++外掛通用模組,其外掛既能靈活

組合到各種系統,又能單獨拆開使用。X3是開發代號,不是版本號。

X3外掛基礎模組用於開發具有統一介面標準的C++外掛模組,使其具有COM元件的多種特點(介面與實現分離,一個實現支援多個介面,引用技術管理,模組獨立

編譯,透明部署,模組可替換等),同時簡單易用,輕量化,這樣開發人員就能簡單快捷的開發出可重用、易於測試的規範模組。

所有外掛都是普通DLL,通過在工程內包含輔助檔案自動實現了統一的匯出函式,通過該匯出函式就能獲取到在該外掛內所實現的所有介面的資訊及物件建立函式

地址;主程式使用外掛管理器(PluginManager)載入這些DLL,外掛管理器通過這個匯出函式將各個類ID、物件建立函式地址統一管理起來,從而在外掛管理器的

中介作用下讓各個外掛能相互使用各種介面函式。

1.2 本模組的特點

採用本模組提供的機制和程式碼檔案來開發外掛模組,具有下列主要特點。

a)介面定義簡單靈活

採用普通的C++介面,既由純虛擬函式組成的結構體,不需要特殊的基類,不需要巨集和UUID宣告;同時可以使用C++的各種變數型別,不受COM介面哪樣的約束。例如

interface Ix_Example

{

virtual void Foo() = 0;

virtual void *GetData(std::vector<int> &items) = 0;

};

3使用方法

a)定義介面

在H檔案中定義介面,在一個H檔案中可以定義一個活多個介面

#pragma once

interface Ix_Example

{

virtual void Foo() = 0;

virtual void *GetData(std::vector<int> &items) = 0;

};

b)定義類UUID

一個元件類如果要讓外接模組能建立物件例項,需要指定元件類的唯一標識資訊,一般採用GUID串來標識元件類。由於普通字串與介面指標都是指標,為了用強型別做區分

採用XCLSID輔助類來封裝類UID,定義類UID常量,供建立物件時之間使用該常量。

既可以在單獨的H檔案中定義類UID常量,也可以和介面定義在同一個H檔案中。

const XCLSID CLSID_Example("FC02CC93-63FF-41CB-A2CF-D05D05F44B23");

c)使用介面

使用智慧指標類Cx_Interface<介面名>來使用介面,呼叫其介面函式;如果在傳遞物件時(例如定義函式引數時)不想包含特定的介面檔案時,可疑使用智慧指標Cx_Ptr。通過

智慧指標類自動管理物件的引用計數和生命週期。


#include <XComPtr>


Cx_Ptr MyFunc1()

{

Cx_Interface<Ix_Example> pIFExample(CLSID_Example);

if(pIFExample)

{

pIFExample->Foo();

}

Cx_Interface<Ix_Example2> pIFExample2(pIFExample);

if(pIFExample2.IsNotNull())

{

pIFExample2->Foo2();

}

MyFunc2(Cx_Ptr(PIFExample2));

return Cx_Ptr(pIFExample2);

}

void MyFunc2(const Cx_Ptr &obj)

{

Cx_Interface<Ix_Example> PIFExample(obj);

if(pIFExample)

{

pIFExample->Foo();

}

}


d) 實現介面

在外掛內部按普通類的方式來實現一個或多個介面,具體就是在類定義中包含介面檔案,實現類從介面派生並實現其介面函式。

#pragma once

#include <Ix_Example.h>

class Cx_Example : public Ix_Example,public Ix_Example2

{

protected:

Cx_Example();

~Cx_Example();

virtual void Foo();

virtual void Foo2();

}

上面的例子中有兩個地方值得留意:一個是建構函式和解構函式是保護型別,標識不允許直接例項化物件,也不允許直接刪除銷燬物件,通過智慧指標類Cx_Interface或Cx_Ptr

來自動例項化和銷燬物件;另一個是所實現的Foo() 等介面函式宣告為保護型別,標識不允許直接呼叫該物件例項的函式,當然也可以宣告為私有型別,標識不允許派生實現

類呼叫其函式。


e)在外掛內登記實現類

外掛中的實現類一般不直接用於例項化物件,是通過智慧指標類Cx_Interface或Cx_Ptr來例項化物件,需要在外掛內登記該外掛中有哪些可供例項化的類,實現類對應的類UID

是否為單例項類。


#include "stdafx.h"

#include <XModuleMacro.h>

#include <XModuleImpl.h>


#include "Cx_Example.h"

#include "Cx_ExampleTool.h"

XBEGIN_DEFINE_MODULE()

XDEFINE_CLASSMAP_ENTRY(CLSID_Example,Cx_Example)

XDEFINE_CLASSMAP_ENTRY_Singleton(CLSID_ExampleTool,Cx_ExampleTool)

XEND_DEFINE_MODULE()


其中包含XModuleImpl.h用於自動實現外掛內部機制,外掛機制如何實現對外掛開發者來說不用關心,巨集XDEFINE_CLASSMAP_ENTRY用於登記普通類及其類UUID,可例項化出多個物件,XDEFINE_CLASSMAP_ENTRY_Singleton用於登記單例項類及其類UUID,在程式中屬於靜態例項

對於以MFC擴充套件動態庫或Win32動態庫型別建立外掛工程的情況,由於DLL入口函式基本上都相同,為了避免在多個外掛中重複出現類似的DLL入口函式程式碼,可以將上面例子中的XEND_DEFINE_MODULE作為下面兩個巨集之一

XEND_DEFINE_MODULE_MFXEXTDLL

XEND_DEFINE_MODULE_WIN32DLL



1.3  新建外掛工程的說明

對於VC++,支援各種型別的工程,例如可在MFC應用程式、MFC常規動態庫、MFC擴充套件動態庫、Win32動態庫中實現外掛功能,在ActiveX控制元件、ATL COM控制元件、Win32控制檯程式、MFC應用程式、各種動態庫工程中使用外掛介面

要開發一個外掛,通常可使用兩種型別的工程,MFC擴充套件動態庫,Win32動態庫。採用MFC擴充套件動態庫相對於MFC常規動態庫的好處是不需要頻繁的切換MFC模組狀態。


不論採用哪種型別的工程來開發外掛,除了設定必要的標頭檔案包含路徑外,所做的額外改動工作如下:

在StdAfx.h中包含XComPtr.h檔案,以便使用智慧指標類Cx_Interface

在一個CPP檔案(Module.cpp)中包含XModuleMacro.h和XModuleImpl.h檔案,使用XBEGIN_DEFINE_MODULE等巨集來登記可能的實現類;


對於不需要實現外掛介面而只想使用介面的工程,例如ActiveX控制元件,可以在一個CPP檔案中包含XComCreator.h檔案,不需要XBEGIN_DEFINE_MODULE等巨集和外掛實現所需要的幾個H檔案


1.4 檔案清單說明

pkg_Core\Interface              外掛框架核心介面目錄,所有工程都需要

Ix_Object                        基本介面定義,所有工程都需要

XComPtr.h                     智慧指標類,所有工程都需要

Ix_ObjectFactory.h      供XModuleImpl.h或XComCreator.h使用

pkg_Core\Interface\Module         外掛實現時所需要的檔案

Ix_Module.h                             獲取自身外掛的資訊

XModuleMacro.h                    外掛中實現類登記所用的巨集定義

XModuleImpl.h                       外掛機制實現檔案

pkg_core\Interface\PluginManager        供載入外掛使用

XComCreator.h                                   供不實現外掛而僅使用外掛介面時包含

Ix_PluginLoader.h                               外掛載入和解除安裝

PluginManager                                   封裝外掛管理器,外掛載入和解除安裝














相關文章