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

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

linux下C++ 插件(plugin)實現(xiàn)技術(shù)

文章來源:http://masterdog.bokee.com/563395.html
?
?????應(yīng)用程序中使用插件技術(shù),有利于日后的版本更新、維護(比如打補丁)和功能擴展,是一種很實用的技術(shù)。其最大的特點是更新插件時無需重新編譯主程序,對于一個設(shè)計良好的應(yīng)用系統(tǒng)而言,甚至可以做到業(yè)務(wù)功能的在線升級。本文介紹了linux下用C++實現(xiàn)插件的一個簡單實例,希望能對大家有所啟發(fā)。

為了能做到更新插件時無需重新編譯主程序,要求主程序中定義的接口是定死的,而接口的實現(xiàn)被放到了具體的插件中,這樣主程序在運行時刻將插件加載進來,就可以使用這些接口所提供的功能了。在面向?qū)ο蟮南到y(tǒng)中,各個功能模塊被封裝到類中,因此在C++中實現(xiàn)插件技術(shù),就需要在主程序中提供基類,并為這些基類定義明確的接口,然后在插件(動態(tài)庫或共享庫)中定義派生類,并實現(xiàn)基類中所有的接口。

我們以計算多邊形面積為例,首先定義一個基類CPolygon:

/* +******************************************************* */
/* +******************************************************* */
/* +******************************************************* */

/* ?polygon.h? */

#ifndef?__POLYGON_H__
#define ?__POLYGON_H__

#include?
< ?iostream? >

class ?CPolygon
{
public :

????CPolygon()
{}

????
virtual ? ~ CPolygon() {}

????
virtual ? double ?area( void )? const ? = ? 0 ;
}
;

#endif ?/*?__POLYGON_H__?*/

/* -******************************************************* */
/* -******************************************************* */
/* -******************************************************* */

注意基類不一定是虛類(有純虛函數(shù)的類),但是接口一定要定義成虛函數(shù),因為最終主程序是通過基類指針
來調(diào)派生類的接口函數(shù),另外如果基類中有資源分配(new)的話,析構(gòu)函數(shù)一定要定義成虛的,否則不會被
調(diào)用,造成內(nèi)存泄漏。

接下來要定義派生類,并放到共享庫(triangle.so)中:

/* +******************************************************* */
/* +******************************************************* */
/* +******************************************************* */

/* ?triangle.h? */

#ifndef?__TRIANGLE_H__
#define ?__TRIANGLE_H__

#include?
" ?polygon.h? "
#include?
< ?iostream? >

class ?CTriangle?:? public ?CPolygon
{
public :

????
virtual ? double ?area( void )? const ;

}
;

#endif ?/*?__TRIANGLE_H__?*/


/* ?triangle.cpp? */

#include?
" triangle.h "

extern ? " C "
{
????
void ? * ?create()
????
{
????????
return ? new ?CTriangle;
????}


}


double ?CTriangle::area( void )? const
{
????std::cout?
<< ? " area?of?triangle " ? << ?std::endl;
????
return ? 0 ;
}


/* -******************************************************* */
/* -******************************************************* */
/* -******************************************************* */

其中定義了函數(shù)“create”用來創(chuàng)建CTriangle類對象,該函數(shù)可讓主程序獲得CTriangle對象指針,從而
可以訪問CTriangle類對象。主程序通過調(diào)用dlsym獲取指向該函數(shù)的指針,需要指出的是,由于dlsym被
設(shè)計成c-style方式,因此調(diào)用c++定義的函數(shù)時,需要加上extern "C"

那么主程序是如何調(diào)用共享庫的呢,代碼片段如下:

/* +******************************************************* */
/* +******************************************************* */
/* +******************************************************* */

typedef?CPolygon
* ?create_t();

void ? * ?handle? = ?dlopen( " triangle.so " ,?RTLD_LAZY);

if (? ! handle?)
{
?std::cerr?
<< ?dlerror()? << ?std::endl;
?exit(
1 );
}


create_t?
* ?create_triangle? = ?(create_t? * )dlsym(handle,? " create " );

CPolygon?
* ?pObj? = ?create_triangle();

if (? 0 ? != ?pObj?)
{
?pObj
-> area();
}


delete?pObj;

dlclose(handle);

/* -******************************************************* */
/* -******************************************************* */
/* -******************************************************* */

主程序通過dlopen打開triangle.so,然后通過dlsym得到庫中的函數(shù)create指針,調(diào)用create后返回了
指向CTriangle類對象的指針,類型是CPolygon的,由于虛函數(shù)的多態(tài)性, pObj->area() 實際是調(diào)用
了CTriangle::area.

好了,插件技術(shù)就是這么簡單,回顧一下實現(xiàn)過程:寫一個基類,定義接口函數(shù),然后在共享庫中寫
派生類,最后在主程序運行時刻打開共享庫(dlopen),并通過create函數(shù)得到指向新創(chuàng)建的派生類
對象的指針,然后利用虛函數(shù)的多態(tài)性,調(diào)用派生類的各種方法。


不過進一步使用后你可能會發(fā)現(xiàn),這樣實現(xiàn)會有些問題:

1. 每寫一個派生類就需要重寫一個create函數(shù)

注意到CTriangle類實現(xiàn)時定義的create函數(shù)必須返回 new CTriangle:

?

extern ? " C "
{
????
void ? * ?create()
????
{
????????
return ? new ?CTriangle;
????}


}

?

那么如果再建一個類比如CRectangle, create函數(shù)必須重寫,返回 new CRectangle

這樣做一方面麻煩,另外CTriangle、CRectangle兩個類不能放到同一個共享庫中,否則會編譯時刻
提示重復(fù)定義錯誤。


2. 主程序無法判斷create函數(shù)返回的是哪個類所創(chuàng)建的對象

當只有一個基類(CPolygon)時主程序當然知道返回的是CPolygon派生類的對象指針:
create_t * create_triangle = (create_t *)dlsym(handle, "create");
CPolygon * pObj = create_triangle();

假如有多個基類,根據(jù)這些基類派生出不同類型的類時,無法在主程序中判斷返回的是那個類的對象。


3. 操作繁瑣

沒有一個統(tǒng)一的操作界面,實現(xiàn)共享庫的加載、卸載、派生類對象的創(chuàng)建,特別是當需要加載一個目錄
下所有的共享庫時,感覺一個一個地加載太麻煩了,能不能批量加載呢。


通過動態(tài)類加載和建立Helper類可以很好地解決上述問題,其中dynclass.h/dynclass.cpp中實現(xiàn)了動態(tài)
加載類對象,pluginhelper.h/pluginhelper.cpp實現(xiàn)了Plugin Helper,具體細節(jié)見附件。


下面簡單介紹一下使用步驟:


1. 首先定義基類(CPolygon),方法同上

2. 在共享庫中實現(xiàn)派生類

比如CTriangle:

/* +******************************************************* */
/* +******************************************************* */
/* +******************************************************* */

/* ?triangle.h? */

#ifndef?__TRIANGLE_H__
#define ?__TRIANGLE_H__

#include?
" ?polygon.h? "
#include??
< ?iostream? >

class ?CTriangle?:? public ?CPolygon
{
public :

????
virtual ? double ?area( void )? const ;

}
;

#endif ?/*?__TRIANGLE_H__?*/


/* ?triangle.cpp? */

#include?
" ?triangle.h? "
#include?
" ?dynclass.h? "

DYN_DECLARE(CTriangle);

double ?CTriangle::area( void )? const
{
????std::cout?
<< ? " area?of?triangle " ? << ?std::endl;
????
return ? 0 ;
}


/* -******************************************************* */
/* -******************************************************* */
/* -******************************************************* */


注意到此時派生類的實現(xiàn)(triangle.cpp)中已沒有了那個討厭的create了,被我偷偷放到
dynclass.cpp中了:

extern ? " C "
{
????
void ? * ?createByClassName( const ? char ? * ?strClassName)
????
{
????????
return ?DYN_CREATE(strClassName);
????}

}


由于對任何派生類而言,該函數(shù)的實現(xiàn)都一樣,因此只需要實現(xiàn)一次,對使用者是不可見的,達到
了從派生類中拿走的目的。

另外增加了一個宏:DYN_DECLARE(CTriangle); 參數(shù)是類名(這里用到了RTTI),每個派生類對應(yīng)
一個這樣的宏,該類就可以支持類對象的動態(tài)加載了,需要包含頭文件dynclass.h


2. 在主程序中如何使用

使用起來也非常簡單,在主程序(main.cpp)中:

/* +******************************************************* */
/* +******************************************************* */
/* +******************************************************* */


#include?
" ?pluginhelper.h? "
#include?
" ?polygon.h? "



CPluginHelper?pluginHelper;

pluginHelper.Load(?
" ./plugin " ,? " *.so " ?);

CPolygon?
* ?pbase? = ?(CPolygon? * )pluginHelper.Create( " CTriangle " );

if (? 0 ? != ?pbase?)
{
????pbase
-> area();
}


delete?pbase;

pluginHelper.Unload(?
" ./plugin " ,? " *.so " ?);

/* -******************************************************* */
/* -******************************************************* */
/* -******************************************************* */

首先定義CPluginHelper對象,調(diào)用Load方法加載共享庫,其中第一個參數(shù)是共享庫的路徑,第二
個參數(shù)是共享庫的名稱,共享庫名支持模式匹配,這里表示要加載./plugin目錄所有so共享庫,
當然也可以是某個具體的共享庫名。

隨后可以通過CPluginHelper::Create方法,根據(jù)類名稱創(chuàng)建該類的對象,實現(xiàn)了參數(shù)化創(chuàng)建對象
的目的,然后就是對該對象的調(diào)用,當不用該對象時,需要調(diào)用delete來刪除。

最后,調(diào)用CPluginHelper::Unload將指定共享庫卸載。

http://masterdog.bokee.com/inc/20050116132524159116.zip

posted on 2006-08-26 04:37 楊粼波 閱讀(829) 評論(0)  編輯 收藏 引用 所屬分類: C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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成人福利| 国产视频精品xxxx| 欧美激情成人在线| 欧美性大战久久久久久久| 欧美专区亚洲专区| 欧美xx视频| 欧美一区二区三区在线播放| 欧美在线视频一区| 久久亚洲精品视频| 亚洲视频一二三| 午夜一区不卡| 9色精品在线| 性xx色xx综合久久久xx| 91久久午夜| 亚洲欧美一区二区三区久久 | 一区二区电影免费观看| 国产午夜精品视频| 日韩亚洲欧美中文三级| 激情综合自拍| 亚洲一级特黄| 日韩午夜三级在线| 久久久999成人| 亚洲欧美日韩精品久久奇米色影视| 欧美亚洲网站| 亚洲性色视频| 欧美岛国激情| 免费在线亚洲欧美| 国产日本欧美一区二区| 91久久极品少妇xxxxⅹ软件| 国产精品区一区二区三| 亚洲黄色免费电影| 亚洲成色最大综合在线| 欧美亚洲免费| 亚洲女同同性videoxma| 欧美精品一级| 亚洲国产综合在线| 在线精品福利| 久久精品首页| 久久久蜜桃一区二区人| 国产精品视频成人| 亚洲午夜激情网页| 亚洲一区日韩在线| 国产精品a级| 一区二区日本视频| 亚洲视频国产视频| 欧美日韩国产一区二区三区地区| 欧美国产精品v| 在线观看精品一区| 久久久一二三| 免费欧美日韩国产三级电影| 一区二区三区我不卡| 久久精品亚洲一区二区| 久久网站免费| 亚洲成人在线网| 美国成人直播| 亚洲国产高清一区二区三区| 91久久精品国产91性色tv| 久久麻豆一区二区| 欧美激情一区二区三区成人| 亚洲国产日韩欧美一区二区三区| 久久日韩粉嫩一区二区三区| 欧美电影免费观看高清完整版| 樱桃成人精品视频在线播放| 久久综合色一综合色88| 亚洲承认在线| 国产精品99久久久久久久vr | 午夜视频久久久久久| 久久久夜精品| 亚洲精华国产欧美| 欧美日韩国产三区| 亚洲一区二区日本| 久久综合国产精品台湾中文娱乐网| 尤物99国产成人精品视频| 麻豆精品国产91久久久久久| 亚洲一区二区动漫| 国产女人18毛片水18精品| 欧美一级大片在线观看| 欧美激情精品久久久久久久变态| 亚洲美女av黄| 欧美视频一区二区在线观看| 性做久久久久久| 亚洲福利国产| 香蕉国产精品偷在线观看不卡| 国产亚洲一级| 欧美日韩国产一中文字不卡| 亚洲欧美日韩国产中文| 亚洲第一区中文99精品| 亚洲欧美日韩国产综合在线 | 亚洲黑丝在线| 国产精品视频网| 久久久一本精品99久久精品66| 亚洲美女色禁图| 免费在线日韩av| 午夜精品久久久久久久99水蜜桃| 亚洲高清一区二| 国产精品丝袜久久久久久app| 狂野欧美激情性xxxx| 亚洲一二三区视频在线观看| 欧美国产综合视频| 欧美自拍丝袜亚洲| 一区二区三区高清在线| 在线观看欧美日韩国产| 国产精品一区一区三区| 欧美激情四色| 久久天堂精品| 亚洲欧美日本国产有色| 亚洲精品日韩激情在线电影| 欧美不卡在线视频| 久久久91精品| 销魂美女一区二区三区视频在线| 亚洲精品乱码久久久久久黑人| 国产一级精品aaaaa看| 国产精品电影观看| 欧美日本精品| 欧美成人精品高清在线播放| 久久国产精品久久久久久| 午夜精品三级视频福利| 一区二区三区视频在线播放| 亚洲人午夜精品| 欧美成人一区在线| 免费观看一区| 男同欧美伦乱| 免费欧美高清视频| 欧美成人免费全部观看天天性色| 久久精品免费| 久久天堂av综合合色| 久久久久九九九九| 久久久久久久性| 久久亚洲一区二区三区四区| 久久精品理论片| 麻豆久久久9性大片| 久久综合一区| 欧美韩日视频| 亚洲国产精品激情在线观看| 亚洲激情成人| 日韩亚洲欧美高清| 中文亚洲视频在线| 亚洲免费在线| 久久精品欧美日韩| 久久亚洲欧美国产精品乐播| 麻豆国产va免费精品高清在线| 美女精品视频一区| 欧美精品18videos性欧美| 欧美日韩精品欧美日韩精品| 欧美三区视频| 国产午夜亚洲精品羞羞网站| 狠狠做深爱婷婷久久综合一区 | 国产一级揄自揄精品视频| 亚洲人成网站在线观看播放| 亚洲国产成人av| 亚洲狼人综合| 亚洲欧美电影在线观看| 久久狠狠一本精品综合网| 久久久久久夜| 亚洲国产视频a| 正在播放亚洲一区| 久久精品在线播放| 欧美国产视频日韩| 国产精品一区免费视频| 在线国产欧美| 亚洲欧美日韩系列| 欧美成人日本| 亚洲午夜伦理| 美玉足脚交一区二区三区图片| 欧美日产一区二区三区在线观看| 国产欧美精品在线播放| 91久久国产综合久久蜜月精品 | 男人天堂欧美日韩| 亚洲色图自拍| 美女日韩在线中文字幕| 欧美日韩午夜剧场| 精品二区视频| 亚洲综合国产| 亚洲国产va精品久久久不卡综合| 亚洲午夜av电影| 欧美激情 亚洲a∨综合| 国产亚洲电影| 亚洲午夜精品久久久久久浪潮| 久久激五月天综合精品| 日韩视频在线观看| 久久精品道一区二区三区| 国产精品草莓在线免费观看| 在线看日韩欧美| 午夜在线a亚洲v天堂网2018| 最新日韩在线视频| 久久亚洲精品伦理| 国产一区二区三区视频在线观看| 一区二区三区国产| 亚洲国产一区二区三区青草影视 |