電子科大李老師Linux實(shí)驗(yàn)四_第1頁
電子科大李老師Linux實(shí)驗(yàn)四_第2頁
電子科大李老師Linux實(shí)驗(yàn)四_第3頁
電子科大李老師Linux實(shí)驗(yàn)四_第4頁
電子科大李老師Linux實(shí)驗(yàn)四_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論