




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、電 子 科 技 大 學(xué)實(shí) 驗(yàn) 報(bào) 告學(xué)生姓名: 學(xué) 號(hào): 指導(dǎo)教師:李林實(shí)驗(yàn)地點(diǎn): 實(shí)驗(yàn)時(shí)間:Csdn全部資源下載地址:一、實(shí)驗(yàn)室名稱:Linux環(huán)境高級(jí)編程實(shí)驗(yàn)室二、實(shí)驗(yàn)項(xiàng)目名稱:插件框架實(shí)驗(yàn)三、實(shí)驗(yàn)學(xué)時(shí):4學(xué)時(shí)四、實(shí)驗(yàn)?zāi)康模盒枰f明為什么要進(jìn)行本次實(shí)驗(yàn)五、實(shí)驗(yàn)內(nèi)容:n 版本1:開發(fā)一個(gè)程序,向屏幕打印“Hello World”;在不重新編譯鏈接原程序的前提下,將打印的文字改為“Hello China”思想:將打印函數(shù)編譯為一個(gè)動(dòng)態(tài)鏈接庫文件,然后測(cè)試程序用顯式調(diào)用的方式,加載動(dòng)態(tài)鏈接庫,并調(diào)用其中的打印函數(shù)。此后要改變輸出內(nèi)容,只需要重新編譯動(dòng)態(tài)鏈接庫文件,而無需對(duì)測(cè)試程序進(jìn)行修改。動(dòng)態(tài)鏈
2、接庫源文件代碼(導(dǎo)出打印函數(shù)),print.cpp:#include <iostream>using namespace std;/打印函數(shù)定義extern "C" void Print() cout << "Hello World!" << endl;測(cè)試程序源代碼,test.cpp:#include <dlfcn.h>#include <iostream>using namespace std;/主程序,測(cè)試動(dòng)態(tài)鏈接庫int main() /打開動(dòng)態(tài)鏈接庫文件 void *handle =
3、dlopen("./libprint.so", RTLD_LAZY); if(handle = 0) /打開失敗 cout << "dlopen error" << endl; return 0; /定義一個(gè)函數(shù)指針類型 typedef void (*FUNC_PRINT)(); /映射打印函數(shù)地址 FUNC_PRINT dl_print = (FUNC_PRINT)dlsym(handle, "Print"); if(dl_print = 0) cout << "dlsym error&
4、quot; << endl; return 0; /調(diào)用打印函數(shù) (dl_print)(); /卸載動(dòng)態(tài)鏈接庫 dlclose(handle); return 0;先編譯測(cè)試程序再編譯動(dòng)態(tài)鏈接庫運(yùn)行測(cè)試程序,輸出Hello World修改print.cpp里的輸出內(nèi)容為Hello China重新編譯動(dòng)態(tài)鏈接庫文件之后,再運(yùn)行測(cè)試程序,輸出了Hello Chinan 版本2要求:同時(shí)要打印“Hello World”,打印“Hello China”,甚至同時(shí)打印未來才會(huì)增加的其他打印信息打印未來的這些信息,也不能重新編譯鏈接原程序思想:使用插件的思想,將所有的動(dòng)態(tài)鏈接庫文件放置在一個(gè)p
5、lugin的文件夾中,然后測(cè)試程序去遍歷該目錄,依次打開所有的動(dòng)態(tài)鏈接庫文件,并調(diào)用其中的Print函數(shù)。另外遍歷目錄獲取動(dòng)態(tài)鏈接庫文件名這個(gè)任務(wù),定義一個(gè)單獨(dú)的工具類來實(shí)現(xiàn)。第一個(gè)動(dòng)態(tài)鏈接庫源代碼,print_world.cpp:#include <iostream>using namespace std;/打印函數(shù)定義extern "C" void Print() cout << "Hello World!" << endl;第二個(gè)動(dòng)態(tài)鏈接庫源代碼,print_china.cpp:#include <iost
6、ream>using namespace std;/打印函數(shù)定義extern "C" void Print() cout << "Hello China!" << endl;插件文件搜索類頭文件,CPluginSeacher.h:#ifndef CPLUGINSEARCHER_H#define CPLUGINSEARCHER_H#include <vector>#include <string>using namespace std;/插件搜索類聲明class CPluginSeacherpublic
7、: CPluginSeacher(); virtual CPluginSeacher(); /獲取所有的插件文件名 bool GetPluginNames(vector<string>& vstrPluginNames);#endif插件文件搜索類源文件,CPluginSeacher.cpp:#include "CPluginSeacher.h"#include <dirent.h>#include <string.h>CPluginSeacher:CPluginSeacher()CPluginSeacher:CPluginSea
8、cher()/獲取所有的插件文件名bool CPluginSeacher:GetPluginNames(vector<string>& vstrPluginNames) /打開當(dāng)前目錄下的plugin目錄 DIR *dir = opendir("./plugin"); if(dir = 0) return false; /循環(huán)讀取所有文件 for(;) /讀一個(gè)文件 struct dirent *pentry = readdir(dir); if(pentry = 0) break; /當(dāng)前目錄,跳過 if(strcmp(pentry->d_nam
9、e, ".") = 0) continue; /上級(jí)目錄,跳過 if(strcmp(pentry->d_name, ".") = 0) continue; /其它文件,則加上目錄前綴,保存到數(shù)組中 string str = "./plugin/" str += pentry->d_name; vstrPluginNames.push_back(str); /關(guān)閉目錄 closedir(dir); return true;測(cè)試程序源文件,test.cpp:#include <dlfcn.h>#include &l
10、t;iostream>#include "CPluginSeacher.h"using namespace std;/主程序,測(cè)試遍歷目錄,調(diào)用所有動(dòng)態(tài)鏈接庫int main() /存放所有動(dòng)態(tài)鏈接庫的文件名 vector<string> vstrPluginNames; /定義插件搜索類對(duì)象 CPluginSeacher enumerator; /獲取所有的插件文件名 if(!enumerator.GetPluginNames(vstrPluginNames) cout << "GetPluginNames error"
11、<< endl; return 0; /遍歷文件名數(shù)組,依次打開并調(diào)用 for(int i = 0; i< vstrPluginNames.size(); i+) /打開動(dòng)態(tài)鏈接庫文件 void *handle = dlopen(vstrPluginNamesi.c_str(), RTLD_LAZY); if(handle = 0) cout << "dlopen error" << endl; return 0; /定義一個(gè)函數(shù)指針類型 typedef void (*FUNC_PRINT)(); /映射打印函數(shù)地址 FUNC_PR
12、INT dl_print = (FUNC_PRINT)dlsym(handle, "Print"); if(dl_print = 0) cout << "dlsym error" << endl; return 0; /調(diào)用打印函數(shù) (dl_print)(); /卸載動(dòng)態(tài)鏈接庫 dlclose(handle); return 0;先編譯測(cè)試程序再編譯兩個(gè)插件(動(dòng)態(tài)鏈接庫)把兩個(gè)插件放到plugin目錄運(yùn)行測(cè)試程序,正確調(diào)用了所有插件中定義的打印函數(shù)n 版本3要求:n 版本2是同時(shí)調(diào)用所有插件的打印功能,現(xiàn)在要求一次只調(diào)用一種功能n
13、 3-1:通過命令行方式:./a.out help,輸出所有插件實(shí)現(xiàn)的功能ID,以及該功能ID對(duì)應(yīng)的功能描述(參考代碼3)n 3-2:通過命令行方式:./a.out FuncID,調(diào)用具體打印功能(每個(gè)插件導(dǎo)出GetID接口)思想:每一個(gè)插件要導(dǎo)出三個(gè)函數(shù),分別是Print、Help和GetID。程序啟動(dòng)后,加載所有插件,把它們的導(dǎo)出函數(shù)的地址用三個(gè)vector分別保存起來。然后根據(jù)用戶的輸入,進(jìn)行對(duì)應(yīng)的調(diào)用。插件1源代碼,print_world.cpp#include <iostream>using namespace std;/打印函數(shù)定義extern "C"
14、; void Print() cout << "Hello World!" << endl;/幫助函數(shù)extern "C" void Help() cout << "This function prints 'Hello World!'" << endl;/返回插件功能IDextern "C" int GetID() return 1;插件2源代碼,print_china.cpp#include <iostream>using namesp
15、ace std;/打印函數(shù)定義extern "C" void Print() cout << "Hello China!" << endl;/幫助函數(shù)extern "C" void Help() cout << "This function prints 'Hello China!'" << endl;/返回插件功能IDextern "C" int GetID() return 2;插件文件搜索類的代碼與上相同,省略。測(cè)試程序代碼,
16、test.cpp#include <dlfcn.h>#include <iostream>#include <string.h>#include <stdlib.h>#include "CPluginSeacher.h"using namespace std;/打印函數(shù)指針類型typedef void (*FUNC_PRINT)();/幫助函數(shù)指針類型typedef void (*FUNC_HELP)();/獲取ID函數(shù)的指針類型typedef int (*FUNC_GETID)();/主程序,測(cè)試代碼int main (in
17、t argc, char *argv) /存放所有插件的文件名 vector<string> vstrPluginNames; /定義插件搜索類對(duì)象 CPluginSeacher enumerator; /獲取所有的插件文件名 if(!enumerator.GetPluginNames(vstrPluginNames) cout << "GetPluginNames error" << endl; return 0; int pluginCount = 0; vector<FUNC_PRINT> vecPrint; vecto
18、r<FUNC_HELP> vecHelp; vector<FUNC_GETID> vecGetid; /遍歷文件名數(shù)組,依次打開并獲取導(dǎo)出函數(shù)地址 for(int i = 0; i< vstrPluginNames.size(); i+) /打開動(dòng)態(tài)鏈接庫文件 void *handle = dlopen(vstrPluginNamesi.c_str(), RTLD_LAZY); if(handle = 0) cout << "dlopen error" << endl; return 0; /獲取打印函數(shù)地址 vecPr
19、int.push_back( (FUNC_PRINT)dlsym(handle, "Print") ); /獲取幫助印函數(shù)地址 vecHelp.push_back( (FUNC_HELP)dlsym(handle, "Help") ); /獲取ID函數(shù)地址 vecGetid.push_back( (FUNC_GETID)dlsym(handle, "GetID") ); +pluginCount; /獲取用戶輸入的參數(shù) if (argc > 1) char* param = argv1; if ( !strcmp(param,
20、"help") ) /用戶輸入的是help /循環(huán),顯示所有插件的功能ID和幫助信息 for (int i = 0; i < pluginCount; i+) cout << vecGetidi() << ": " /輸出ID vecHelpi(); /調(diào)用幫助信息函數(shù) else /用戶可能輸入的是功能ID int id = atoi(param); /循環(huán),找出該功能 for (int i = 0; i < pluginCount; i+) if (vecGetidi() = id) /找到了 vecPrinti()
21、; /調(diào)用其打印函數(shù) return 0;先編譯測(cè)試程序編譯插件1編譯插件2將兩個(gè)插件放入plugin目錄測(cè)試幫助信息調(diào)用功能1調(diào)用功能2n 版本4要求:n 在版本3中,插件導(dǎo)出了Print、GetID、Help三個(gè)函數(shù),主程序需要使用多個(gè)容器分別保存這些函數(shù)地址n 在復(fù)雜的業(yè)務(wù)邏輯中,導(dǎo)出的函數(shù)可能更多,若還按照版本3的方式,代碼維護(hù)性不佳n 將三個(gè)導(dǎo)出函數(shù)都放在一個(gè)類中,讓插件外部獲取該類的對(duì)象思想:定義一個(gè)插件接口類,所有插件類繼承自這個(gè)接口類,并覆蓋其中的三個(gè)方法,然后動(dòng)態(tài)鏈接庫的導(dǎo)出函數(shù),返回類型為父類指針類型,創(chuàng)建一個(gè)插件類對(duì)象,返回其指針即可。插件接口類代碼,CPluginInte
22、rface.h#ifndef CPLUGININTERFACE_H_#define CPLUGININTERFACE_H_class CPluginInterfacepublic: virtual void Print() ; virtual void Help() ; virtual int GetID() return 0; CPluginInterface(); CPluginInterface();#endif插件1代碼,print_world.cpp#include <iostream>#include "CPluginInterface.h"usin
23、g namespace std;class Plugin : public CPluginInterface public: Plugin() virtual void Print() cout << "Hello World!" << endl; virtual void Help() cout << "This function prints 'Hello World!'" << endl; virtual int GetID() return 1; ;/獲取插件接口對(duì)象extern &
24、quot;C" CPluginInterface* getInterface() static Plugin plugin; return &plugin;插件2代碼,print_china.cpp#include <iostream>#include "CPluginInterface.h"using namespace std;class Plugin : public CPluginInterface public: Plugin() virtual void Print() cout << "Hello China
25、!" << endl; virtual void Help() cout << "This function prints 'Hello China!'" << endl; virtual int GetID() return 2; ;/獲取插件接口對(duì)象extern "C" CPluginInterface* getInterface() static Plugin plugin; return &plugin;插件文件搜索類的代碼與上相同,省略。測(cè)試程序代碼,test.cpp#inc
26、lude <dlfcn.h>#include <iostream>#include <string.h>#include <stdlib.h>#include "CPluginSeacher.h"#include "CPluginInterface.h"using namespace std;/導(dǎo)出函數(shù)的指針類型typedef CPluginInterface* (*FUNC_GETINTERFACE)();/主程序,測(cè)試代碼int main (int argc, char *argv) /存放所有插件的文
27、件名 vector<string> vstrPluginNames; /定義插件搜索類對(duì)象 CPluginSeacher enumerator; /獲取所有的插件文件名 if(!enumerator.GetPluginNames(vstrPluginNames) cout << "GetPluginNames error" << endl; return 0; int pluginCount = 0; vector<CPluginInterface*> vecPluginIfs; /遍歷文件名數(shù)組,依次打開并獲取導(dǎo)出的接口對(duì)象 for(int i = 0; i< vstrPluginNames.size(); i+) /打開動(dòng)態(tài)鏈接庫文件 void *handle = dlopen(vstrPluginNames
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 咨詢工程師決策視頻課件
- 2025年醫(yī)藥流通行業(yè)供應(yīng)鏈重構(gòu)與成本控制最佳實(shí)踐報(bào)告
- 2025年虛擬現(xiàn)實(shí)(VR)設(shè)備在虛擬現(xiàn)實(shí)社交中的應(yīng)用現(xiàn)狀與未來發(fā)展趨勢(shì)研究報(bào)告
- 保潔員培訓(xùn)題庫及答案
- 伴性遺傳考試試題及答案
- 醫(yī)療器械臨床試驗(yàn)質(zhì)量管理規(guī)范化與2025年臨床試驗(yàn)數(shù)據(jù)管理報(bào)告
- 中國(guó)電子信息行業(yè)運(yùn)行情況月度報(bào)告(2025年1-4月)
- 安全生產(chǎn)知識(shí)培訓(xùn)試題及答案
- 餐飲外賣市場(chǎng)2025年增長(zhǎng)瓶頸解析:破局策略與行業(yè)發(fā)展趨勢(shì)報(bào)告
- 2025年快時(shí)尚模式在時(shí)尚零售行業(yè)的數(shù)字化營(yíng)銷策略與效果評(píng)估報(bào)告001
- 《人工智能基礎(chǔ)概念》考試復(fù)習(xí)題庫(濃縮300題)
- 端子壓接技術(shù)標(biāo)準(zhǔn)
- 消費(fèi)經(jīng)濟(jì)學(xué)完整整套教學(xué)課件
- 機(jī)械特性測(cè)試儀操作規(guī)程
- 超星學(xué)習(xí)通藝術(shù)美學(xué)(蘇州大學(xué))章節(jié)答案
- 護(hù)理查房高位截癱584
- GA 1524-2018射釘器公共安全要求
- 植物學(xué)第三小組名錄
- 2023年贛南師范大學(xué)科技學(xué)院輔導(dǎo)員招聘考試筆試題庫及答案解析
- 電腦的認(rèn)識(shí) 完整版課件
- 醫(yī)院感染管理制度
評(píng)論
0/150
提交評(píng)論