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

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
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>
            亚洲精品影视| 另类酷文…触手系列精品集v1小说| 亚洲私人影院在线观看| 99re6热只有精品免费观看| 亚洲人体偷拍| 在线一区二区日韩| 亚洲欧美日韩久久精品| 欧美一级淫片播放口| 欧美中文字幕精品| 你懂的国产精品| 亚洲三级免费| 亚洲日本成人| 亚洲综合首页| 久久三级福利| 欧美色123| 在线播放亚洲| 亚洲天堂av在线免费观看| 亚洲欧美制服另类日韩| 美女亚洲精品| 亚洲色在线视频| 久久久国产成人精品| 欧美激情1区2区| 国产精品一二一区| 亚洲国产婷婷香蕉久久久久久99| 亚洲小说欧美另类婷婷| 久久久久.com| 99视频精品| 久久躁日日躁aaaaxxxx| 国产精品人人做人人爽| 亚洲国产精品传媒在线观看| 亚洲欧美久久| 欧美激情一区二区久久久| 亚洲网站在线| 国外精品视频| 欧美日韩大片| 国产亚洲观看| 亚洲视频狠狠| 欧美激情第10页| 欧美在线视频一区二区| 欧美日韩一区二区在线视频| 在线日本高清免费不卡| 欧美中文字幕第一页| 99精品欧美一区二区蜜桃免费| 欧美在线高清视频| 国产精品免费观看视频| 亚洲一区日韩在线| 日韩视频一区| 欧美日韩激情小视频| 亚洲国产女人aaa毛片在线| 香蕉尹人综合在线观看| 亚洲最快最全在线视频| 欧美国产欧美综合 | 亚洲精品少妇网址| 欧美777四色影视在线| 经典三级久久| 久久精品国产一区二区三| 一卡二卡3卡四卡高清精品视频| 欧美成人综合一区| 91久久综合| 亚洲国产成人久久综合| 久久在线播放| 91久久精品国产91久久| 欧美黄网免费在线观看| 美女脱光内衣内裤视频久久影院 | 国产美女诱惑一区二区| 亚洲欧美日韩中文视频| 亚洲综合电影| 国产欧美日韩精品a在线观看| 欧美影院久久久| 欧美一区二区啪啪| 狠狠色噜噜狠狠色综合久| 久久―日本道色综合久久| 久久av二区| 亚洲国产成人午夜在线一区| 欧美大片一区二区| 欧美激情国产日韩| 亚洲欧美日韩国产一区| 亚洲欧美精品| 亚洲高清不卡av| 最新中文字幕一区二区三区| 欧美日韩一二三区| 欧美一区三区三区高中清蜜桃 | 久久精品视频播放| 久久久青草婷婷精品综合日韩 | 国产亚洲一级| 亚洲精品一区二区三区在线观看 | 一区二区三区四区五区精品视频| 欧美日韩一区二区三区免费看| 夜夜夜久久久| 亚洲综合好骚| 亚洲黄色影院| 中文高清一区| 亚洲第一精品电影| 亚洲视频一起| 亚洲三级视频| 午夜视频在线观看一区二区三区| 在线观看一区二区视频| 亚洲美女一区| 亚洲成人自拍视频| 亚洲一区欧美激情| 99精品福利视频| 久久精品国产亚洲一区二区三区 | 国产一区二区三区久久 | 亚洲天堂久久| 久久婷婷久久| 亚洲欧美在线aaa| 欧美成年人网| 久久久综合视频| 国产精品久久久久久久免费软件| 欧美大片一区二区三区| 国产性猛交xxxx免费看久久| 亚洲国产一区二区视频| 好吊日精品视频| 午夜国产一区| 亚洲男同1069视频| 欧美日本簧片| 亚洲国产高潮在线观看| 精品不卡在线| 久久成人精品电影| 久久精品国产一区二区三| 国产精品美女久久久久久2018| 亚洲黄色片网站| 亚洲激情另类| 免费一级欧美片在线播放| 久久综合狠狠综合久久激情| 国产农村妇女毛片精品久久麻豆| 一区二区三区视频在线观看| 亚洲区欧美区| 欧美高清在线播放| 亚洲国产婷婷香蕉久久久久久| 在线观看久久av| 久久香蕉国产线看观看网| 久久亚洲精品视频| 狠狠色综合播放一区二区| 欧美一区二区视频在线| 久久久久国产一区二区三区| 国产女主播在线一区二区| 亚洲一区中文字幕在线观看| 性欧美大战久久久久久久免费观看| 国产精品a久久久久| 在线中文字幕不卡| 欧美伊人久久| 国产一级揄自揄精品视频| 欧美日韩精品在线| 久久精品国产综合精品| 国产精品日韩在线一区| 亚洲一区二区三区乱码aⅴ| 午夜国产精品影院在线观看| 国产精品入口福利| 欧美影院精品一区| 久久综合九色九九| 亚洲国产精品123| 欧美极品aⅴ影院| 日韩亚洲综合在线| 欧美一区二区三区四区视频| 韩国成人精品a∨在线观看| 久久天天狠狠| 日韩视频免费观看高清在线视频| 亚洲欧美日本在线| 禁久久精品乱码| 欧美日韩精品免费看 | 欧美激情精品久久久久久大尺度| 亚洲国产精品成人久久综合一区| 99re视频这里只有精品| 国产精品久久久久天堂| 久久久欧美一区二区| 一道本一区二区| 麻豆成人在线播放| 亚洲视频中文字幕| 国产一区清纯| 欧美日韩免费观看一区=区三区| 亚洲一区二区三区色| 蜜臀a∨国产成人精品| 一本大道久久a久久综合婷婷| 国产农村妇女精品一二区| 欧美大片在线看免费观看| 香蕉成人伊视频在线观看| 亚洲国产日韩综合一区| 久久av资源网站| 99re亚洲国产精品| 国产网站欧美日韩免费精品在线观看| 美女被久久久| 先锋亚洲精品| 亚洲视频国产视频| 亚洲二区视频在线| 久久久国产成人精品| 中国女人久久久| 亚洲国产精品va在线看黑人动漫| 国产精品久久国产三级国电话系列| 久久综合给合久久狠狠狠97色69| 亚洲视频久久| 日韩亚洲不卡在线| 欧美国产一区二区| 久久久精品久久久久| 亚洲欧美在线视频观看| av不卡免费看| 亚洲日本在线视频观看| 一区二区三区在线视频免费观看| 国产精品你懂得| 欧美午夜视频在线|