青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

轉(zhuǎn)自http://www.imyaker.com/blog/article.asp?id=34
插件系統(tǒng)-選擇GetProcAddress還是Interfaces(譯)
原文:
Plugin System – an alternative to GetProcAddress and interfaces
下載文件 代碼下載
[介紹]
有很多文章描述如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的插件框架,比如后面的鏈接[1]和[2]。通常有兩種方法
(1) 插件實(shí)現(xiàn)一組標(biāo)準(zhǔn)的(并且通常是小的)函數(shù)(方法)。宿主(host)知道這些函數(shù)的名字,并且可以通過(guò)使用GetProcAddress函數(shù)獲得這些函 數(shù)的地址。這并不合適,隨著函數(shù)數(shù)量的增長(zhǎng),維護(hù)變得越來(lái)越困難。你必須手動(dòng)通過(guò)函數(shù)名綁定函數(shù),這樣你就不得不做很多工作。
(2)GetProcAddress所返回的函數(shù)被用來(lái)傳遞接口指針(Interface Pointer)給插件或者從插件里獲取接口指針。剩下的宿主和插件的通信通過(guò)接口完成。下面是一個(gè)例子

我 們將使用一個(gè)簡(jiǎn)單的例子。宿主程序是一個(gè)圖片查看器。它實(shí)現(xiàn)了一個(gè)插件框架來(lái)增加對(duì)不同圖片格式的支持(在這個(gè)例子中就是24-bit的BMP圖象和24 -bit的TGA(Targa)圖象)。插件將被實(shí)現(xiàn)為DLLs并且將有.imp的擴(kuò)展名以便和普通dll文件區(qū)分開來(lái)了.注意,盡管如此,可是這篇文章 是關(guān)于插件的,而不是關(guān)于圖象解解析器的。這里所提供的解析器非常基礎(chǔ)并且只是用來(lái)說(shuō)明的。

[使用接口的方法]
接口是所有函數(shù)都是公共的并且純虛的基類,并且沒有沒有數(shù)據(jù)成員。比如
程序代碼 程序代碼
// IImageParser is the interface that all image parsers
// must implement
class IImageParser
{
    public:
    // parses the image file and reads it into a HBITMAP
    virtual HBITMAP ParseFile( const char *fname )=0;
    // returns true if the file type is supported
    virtual bool SupportsType( const char *type ) const=0;
};

實(shí)際的圖象解析器必須繼承自接口類并且實(shí)現(xiàn)純虛函數(shù)。BMP文件解析器可能是這個(gè)樣子。
程序代碼 程序代碼
// CBMPParser implements the IImageParser interface
class CBMPParser: public IImageParser
{
    public:
    virtual HBITMAP ParseFile( const char *fname );
    virtual bool SupportsType( const char *type ) const;

private:
    HBITMAP CreateBitmap( int width, int height, void **data );
};

static CBMPParser g_BMPParser;

// The host calls this function to get access to the
// image parser
extern "C" __declspec(dllexport) IImageParser *GetParser( void )
{
    return &g_BMPParser;
}

宿主將使用LoadLibrary函數(shù)來(lái)載入BmpParser.imp,然后使用GetProcAddress("GetParser")來(lái)得到GetParser函數(shù)的地址,然后調(diào)用它得到IImageParser類的指針。
宿主將保存了注冊(cè)了的解析器的鄰接表(list),它把GetParser函數(shù)返回的指針附加到那個(gè)鄰接表上去。
當(dāng)宿主需要解析一個(gè)bmp文件的時(shí)候,它將調(diào)用每個(gè)解析器的SupportType(".BMP")。如果返回類型是true,宿主將調(diào)用那個(gè)解析器并且使用完整文件名調(diào)用待解析文件,并將繪制HBITMAP句柄指向的位圖。

基類并不真的必須是純接口。在技術(shù)上這里的限制是所有的成員必須可以通過(guò)對(duì)象指針訪問(wèn)。所以你可以有:
- 純虛成員函數(shù)(它們能通過(guò)虛表被間接訪問(wèn))
- 數(shù)據(jù)成員(它們可以通過(guò)對(duì)象的指針直接訪問(wèn))
- 內(nèi)聯(lián)成員函數(shù)(技術(shù)上它們不能通過(guò)指針訪問(wèn),但是它們的代碼又一次在插件里實(shí)例化。
這樣就剩下了非內(nèi)聯(lián)和靜態(tài)成員函數(shù)。插件無(wú)法從宿主訪問(wèn)這樣的函數(shù),宿主也不能對(duì)插件進(jìn)行這樣的操作。不幸的是在一個(gè)大型系統(tǒng)之中,這樣的函數(shù)要占據(jù)代碼的大部分。

例如所有的圖象解析器需要CreateFunction函數(shù)。有必要在基類里聲明它并且在宿主端實(shí)現(xiàn)。否則每個(gè)插件都將有一份這個(gè)函數(shù)的拷貝。
這個(gè)方法的另一個(gè)限制是你不能由宿主端暴露任何全局成員或者全局函數(shù)給插件端。
我們?cè)趺锤倪M(jìn)呢?

[把宿主分成Dll和Exe]
讓 我們看一下USER32模塊,它有兩個(gè)部分 - user32.dll 和 user32.lib。真正的代碼和數(shù)據(jù)在dll中,lib僅僅提供調(diào)用dll函數(shù)的占位函數(shù)。最好的事情在于它是自動(dòng)發(fā)生的。當(dāng)你鏈接到 user32.lib你就自動(dòng)地獲得訪問(wèn)user32.dll函數(shù)的權(quán)利。(這里翻譯的不好)
MFC 實(shí)現(xiàn)得更進(jìn)一步 - 它暴露你能直接使用和繼承的整個(gè)類。它們沒有我們?cè)谏厦嬗懻摰募兲摻涌陬惖南拗啤?br>我 們也能做同樣的事情。任何你想提供給插件的函數(shù)(我私下覺得原文functionality這個(gè)詞用得不好)都能放在一個(gè)單獨(dú)的Dll里。使用 /IMPLIB 鏈接器選項(xiàng)來(lái)創(chuàng)建相應(yīng)的 LIB 文件。插件能與那個(gè)靜態(tài)庫(kù)鏈接,并且所有導(dǎo)出函數(shù)都能提供給它們。你能按你喜歡的方式把代碼分成Dll 和 Exe。極限情況下,像在代碼里演示的那樣,Exe 工程里僅僅含有一行WinMain函數(shù),它僅僅用來(lái)啟動(dòng)Dll。
任何你想要導(dǎo)出的全局?jǐn)?shù)據(jù),函數(shù),類,或者成員函數(shù)必須被標(biāo)記為 __declspec(dllexport) 在編譯插件時(shí)。一個(gè)常用的技巧是使用宏
程序代碼 程序代碼

#ifdef COMPILE_HOST
// when the host is compiling
#define HOSTAPI __declspec(dllexport)
#else
// when the plugins are compiling
#define HOSTAPI __declspec(dllimport)
#endif

添加宏COMPILE_HOST的定義到Dll工程里,但是不加到插件工程里。

在宿主Dll端:
程序代碼 程序代碼

// CImageParser is the base class that all image parsers
// must inherit
class CImageParser
{
public:
    // adds the parser to the parsers list
    HOSTAPI CImageParser( void );
    // parses the image file and reads it into a HBITMAP
    virtual HBITMAP ParseFile( const char *fname )=0;
    // returns true if the file type is supported
    virtual bool SupportsType( const char *type ) const=0;

protected:
    HOSTAPI HBITMAP CreateBitmap( int width, int height,
    void **data );
};

現(xiàn)在基類并不僅僅限于一個(gè)接口。我們能增加更多基本功能。CreateBitmap函數(shù)將被所有解析器共享。
這次不再是宿主調(diào)用一個(gè)函數(shù)來(lái)獲取解析器并且將它添加到鄰接表中,這個(gè)功能被CImageParser的構(gòu)造函數(shù)取代。當(dāng)解析器對(duì)象被創(chuàng)建,它的構(gòu)造函數(shù)將自動(dòng)更新鄰接表。宿主不必再使用GetProcAddress函數(shù)來(lái)看看什么解析器在Dll里。

在插件端:
程序代碼 程序代碼
// CBMPParser inherits from CImageParser
class CBMPParser: public CImageParser
{
public:
    virtual HBITMAP ParseFile( const char *fname );
    virtual bool SupportsType( const char *type ) const;
};

static CBMPParser g_BMPParser;

當(dāng)g_BMPParser被創(chuàng)建是它的構(gòu)造函數(shù) CBMPParser() 將被調(diào)用。那個(gè)構(gòu)造函數(shù)(在插件端實(shí)現(xiàn))將調(diào)用基類的構(gòu)造函數(shù)CImageParser() (在宿主端實(shí)現(xiàn))。那是可能的因?yàn)闃?gòu)造函數(shù)被標(biāo)記為HOSTAPI。
等等,還可以變得更好

[把宿主Dll和Exe連接起來(lái)]
(這一部分暫時(shí)沒翻譯)

[鏈接]
[1] Plug-In framework using DLLs by Mohit Khanna
[2] ATL COM Based Addin / Plugin Framework With Dynamic Toolbars and Menus by thomas_tom99

PS.我想,Interface方法,是在第一種方法之上加入了一個(gè)間接層。
我現(xiàn)在到?jīng)]有太強(qiáng)的感覺非內(nèi)聯(lián)函數(shù)和靜態(tài)函數(shù)會(huì)成為這樣一個(gè)大型系統(tǒng)的主要部分,Interface的派生類中的非內(nèi)聯(lián)函數(shù)應(yīng)該只被純虛接口函數(shù)調(diào)用,不然就是接口設(shè)計(jì)有問(wèn)題了。

posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲日本成人在线观看| 欧美午夜寂寞影院| 亚洲精品国产系列| 久热精品在线视频| 久久久久久综合| 久久久久久久国产| 模特精品裸拍一区| 亚洲高清精品中出| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲成人在线视频播放| 久久黄金**| 媚黑女一区二区| 日韩视频在线一区| 黄色一区二区在线| 蜜臀av在线播放一区二区三区| 美玉足脚交一区二区三区图片| 亚洲理论在线观看| 欧美黄色日本| 亚洲一区二区日本| 亚洲一区免费| 亚洲国产午夜| 亚洲成色777777在线观看影院| 好吊视频一区二区三区四区| 91久久一区二区| 亚洲午夜精品一区二区三区他趣 | 巨胸喷奶水www久久久免费动漫| 欧美大色视频| 国产欧美精品xxxx另类| 亚洲人成艺术| 午夜精品影院在线观看| 亚洲国产免费看| 亚洲欧美成人一区二区在线电影 | 欧美中文字幕在线| 亚洲二区三区四区| 亚洲一区二三| 欧美伦理91| 亚洲成色777777在线观看影院| 亚洲在线视频免费观看| 欧美国产日韩免费| 欧美在线亚洲综合一区| 国产精品电影网站| 亚洲精品乱码久久久久久按摩观| 久久精品最新地址| 亚洲一区中文| 国产精品久久久久久久久久免费 | 欧美在线视频免费播放| 国产精品高精视频免费| 亚洲老板91色精品久久| 欧美激情一区在线观看| 欧美在线啊v| 国产区二精品视| 亚洲专区在线视频| 中文在线资源观看网站视频免费不卡| 欧美成人黑人xx视频免费观看| 国产专区精品视频| 久久国内精品视频| 蜜桃av一区二区三区| 欧美在现视频| 久久激情婷婷| 欧美一区二区三区免费大片| 亚洲午夜国产一区99re久久| 国产精品国产三级国产专区53 | 精品成人一区二区三区四区| 久久久精品午夜少妇| 欧美一区免费视频| 狠狠色狠狠色综合日日五| 久久久夜色精品亚洲| 欧美在线你懂的| 亚洲国产精品传媒在线观看| 欧美成人黑人xx视频免费观看| 久久综合一区二区三区| 最新日韩在线| 亚洲毛片av| 亚洲网站视频福利| 亚洲精品久久久久久久久久久久| 欧美激情在线狂野欧美精品| 99国产精品国产精品久久| 亚洲精品小视频| 欧美性猛交一区二区三区精品| 亚洲欧美国产精品va在线观看| 亚洲综合第一页| 国产日韩在线一区二区三区| 久久久综合网| 欧美国产91| 亚洲欧美制服另类日韩| 久久精品99国产精品日本| 亚洲国产经典视频| 日韩视频不卡| 国产一区二区成人久久免费影院| 老司机精品视频一区二区三区| 六月婷婷一区| 亚洲一区区二区| 久久精品av麻豆的观看方式 | 欧美性一二三区| 久久久久久久久久看片| 欧美丰满高潮xxxx喷水动漫| 在线亚洲精品| 久久欧美中文字幕| 亚洲欧美一区二区视频| 久久久久.com| 亚洲欧美日韩电影| 久久久久九九视频| 亚洲婷婷综合色高清在线| 欧美在线首页| 亚洲手机在线| 欧美激情视频一区二区三区在线播放 | 久久青青草综合| 欧美福利在线观看| 久久久久久久一区二区| 亚洲最新在线视频| 久久伊人免费视频| 亚洲一区二区精品在线| 性做久久久久久免费观看欧美| 亚洲精品在线看| 羞羞答答国产精品www一本| 亚洲久色影视| 久久人人爽人人爽爽久久| 亚洲与欧洲av电影| 欧美国产精品久久| 蜜臀av国产精品久久久久| 国产精品a级| 亚洲人午夜精品| 在线成人www免费观看视频| 在线亚洲精品| 99精品国产热久久91蜜凸| 乱码第一页成人| 久色婷婷小香蕉久久| 国产视频在线观看一区二区三区| 日韩视频在线观看| 99精品欧美一区| 欧美国产专区| 亚洲国产精品成人| 亚洲精品中文字| 免费日韩av片| 亚洲国产黄色| 99视频一区| 欧美性做爰毛片| 中文在线资源观看网站视频免费不卡 | 男人的天堂成人在线| 国产精品网站在线播放| 亚洲尤物视频网| 欧美一区激情| 国产综合激情| 免播放器亚洲一区| 亚洲第一级黄色片| 亚洲精品综合久久中文字幕| 欧美国产日韩一二三区| 亚洲精品九九| 亚洲欧美精品一区| 国产精品激情电影| 午夜精品在线观看| 麻豆精品在线观看| 日韩一级精品| 欧美亚洲成人精品| 久久国产福利| 亚洲高清久久久| 在线综合视频| 国产免费一区二区三区香蕉精| 欧美一区二区三区久久精品茉莉花| 久久精品国产一区二区三区| 韩国av一区二区三区在线观看| 久久香蕉精品| 亚洲精品视频在线观看免费| 午夜在线精品偷拍| 亚洲福利国产精品| 国产精品av久久久久久麻豆网| 亚洲摸下面视频| 欧美jizzhd精品欧美喷水| 一区二区三区精品在线| 国产日产欧产精品推荐色| 老司机67194精品线观看| 亚洲欧洲精品天堂一级| 欧美亚洲一区| 亚洲精品久久久久久一区二区| 国产精品多人| 鲁鲁狠狠狠7777一区二区| 亚洲欧美区自拍先锋| 亚洲免费在线精品一区| 欧美激情视频网站| 午夜久久99| 亚洲精品视频免费在线观看| 国产精品ⅴa在线观看h| 久久久一区二区三区| 老**午夜毛片一区二区三区| 欧美激情一区二区三区在线视频观看| 亚洲天堂激情| 亚洲高清av| 国产精品日本| 欧美—级高清免费播放| 性伦欧美刺激片在线观看| 亚洲美女毛片| 欧美激情精品久久久久久黑人| 欧美一区二区网站| 亚洲午夜精品17c| 亚洲伦理久久| 亚洲国产成人av好男人在线观看| 国产精品久久久久久久一区探花| 欧美sm视频| 久久综合电影| 久久久久久久久一区二区|