电子科大李老师Linux实验四_第1页
电子科大李老师Linux实验四_第2页
电子科大李老师Linux实验四_第3页
电子科大李老师Linux实验四_第4页
电子科大李老师Linux实验四_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、电 子 科 技 大 学实 验 报 告学生姓名: 学 号: 指导教师:李林实验地点: 实验时间:Csdn全部资源下载地址:一、实验室名称:Linux环境高级编程实验室二、实验项目名称:插件框架实验三、实验学时:4学时四、实验目的:需要说明为什么要进行本次实验五、实验内容:n 版本1:开发一个程序,向屏幕打印“Hello World”;在不重新编译链接原程序的前提下,将打印的文字改为“Hello China”思想:将打印函数编译为一个动态链接库文件,然后测试程序用显式调用的方式,加载动态链接库,并调用其中的打印函数。此后要改变输出内容,只需要重新编译动态链接库文件,而无需对测试程序进行修改。动态链

2、接库源文件代码(导出打印函数),print.cpp:#include <iostream>using namespace std;/打印函数定义extern "C" void Print() cout << "Hello World!" << endl;测试程序源代码,test.cpp:#include <dlfcn.h>#include <iostream>using namespace std;/主程序,测试动态链接库int main() /打开动态链接库文件 void *handle =

3、dlopen("./libprint.so", RTLD_LAZY); if(handle = 0) /打开失败 cout << "dlopen error" << endl; return 0; /定义一个函数指针类型 typedef void (*FUNC_PRINT)(); /映射打印函数地址 FUNC_PRINT dl_print = (FUNC_PRINT)dlsym(handle, "Print"); if(dl_print = 0) cout << "dlsym error&

4、quot; << endl; return 0; /调用打印函数 (dl_print)(); /卸载动态链接库 dlclose(handle); return 0;先编译测试程序再编译动态链接库运行测试程序,输出Hello World修改print.cpp里的输出内容为Hello China重新编译动态链接库文件之后,再运行测试程序,输出了Hello Chinan 版本2要求:同时要打印“Hello World”,打印“Hello China”,甚至同时打印未来才会增加的其他打印信息打印未来的这些信息,也不能重新编译链接原程序思想:使用插件的思想,将所有的动态链接库文件放置在一个p

5、lugin的文件夹中,然后测试程序去遍历该目录,依次打开所有的动态链接库文件,并调用其中的Print函数。另外遍历目录获取动态链接库文件名这个任务,定义一个单独的工具类来实现。第一个动态链接库源代码,print_world.cpp:#include <iostream>using namespace std;/打印函数定义extern "C" void Print() cout << "Hello World!" << endl;第二个动态链接库源代码,print_china.cpp:#include <iost

6、ream>using namespace std;/打印函数定义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) /打开当前目录下的plugin目录 DIR *dir = opendir("./plugin"); if(dir = 0) return false; /循环读取所有文件 for(;) /读一个文件 struct dirent *pentry = readdir(dir); if(pentry = 0) break; /当前目录,跳过 if(strcmp(pentry->d_nam

9、e, ".") = 0) continue; /上级目录,跳过 if(strcmp(pentry->d_name, ".") = 0) continue; /其它文件,则加上目录前缀,保存到数组中 string str = "./plugin/" str += pentry->d_name; vstrPluginNames.push_back(str); /关闭目录 closedir(dir); return true;测试程序源文件,test.cpp:#include <dlfcn.h>#include &l

10、t;iostream>#include "CPluginSeacher.h"using namespace std;/主程序,测试遍历目录,调用所有动态链接库int main() /存放所有动态链接库的文件名 vector<string> vstrPluginNames; /定义插件搜索类对象 CPluginSeacher enumerator; /获取所有的插件文件名 if(!enumerator.GetPluginNames(vstrPluginNames) cout << "GetPluginNames error"

11、<< endl; return 0; /遍历文件名数组,依次打开并调用 for(int i = 0; i< vstrPluginNames.size(); i+) /打开动态链接库文件 void *handle = dlopen(vstrPluginNamesi.c_str(), RTLD_LAZY); if(handle = 0) cout << "dlopen error" << endl; return 0; /定义一个函数指针类型 typedef void (*FUNC_PRINT)(); /映射打印函数地址 FUNC_PR

12、INT dl_print = (FUNC_PRINT)dlsym(handle, "Print"); if(dl_print = 0) cout << "dlsym error" << endl; return 0; /调用打印函数 (dl_print)(); /卸载动态链接库 dlclose(handle); return 0;先编译测试程序再编译两个插件(动态链接库)把两个插件放到plugin目录运行测试程序,正确调用了所有插件中定义的打印函数n 版本3要求:n 版本2是同时调用所有插件的打印功能,现在要求一次只调用一种功能n

13、 3-1:通过命令行方式:./a.out help,输出所有插件实现的功能ID,以及该功能ID对应的功能描述(参考代码3)n 3-2:通过命令行方式:./a.out FuncID,调用具体打印功能(每个插件导出GetID接口)思想:每一个插件要导出三个函数,分别是Print、Help和GetID。程序启动后,加载所有插件,把它们的导出函数的地址用三个vector分别保存起来。然后根据用户的输入,进行对应的调用。插件1源代码,print_world.cpp#include <iostream>using namespace std;/打印函数定义extern "C"

14、; void Print() cout << "Hello World!" << endl;/帮助函数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;/打印函数定义extern "C" void Print() cout << "Hello China!" << endl;/帮助函数extern "C" void Help() cout << "This function prints 'Hello China!'" << endl;/返回插件功能IDextern "C" int GetID() return 2;插件文件搜索类的代码与上相同,省略。测试程序代码,

16、test.cpp#include <dlfcn.h>#include <iostream>#include <string.h>#include <stdlib.h>#include "CPluginSeacher.h"using namespace std;/打印函数指针类型typedef void (*FUNC_PRINT)();/帮助函数指针类型typedef void (*FUNC_HELP)();/获取ID函数的指针类型typedef int (*FUNC_GETID)();/主程序,测试代码int main (in

17、t argc, char *argv) /存放所有插件的文件名 vector<string> vstrPluginNames; /定义插件搜索类对象 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; /遍历文件名数组,依次打开并获取导出函数地址 for(int i = 0; i< vstrPluginNames.size(); i+) /打开动态链接库文件 void *handle = dlopen(vstrPluginNamesi.c_str(), RTLD_LAZY); if(handle = 0) cout << "dlopen error" << endl; return 0; /获取打印函数地址 vecPr

19、int.push_back( (FUNC_PRINT)dlsym(handle, "Print") ); /获取帮助印函数地址 vecHelp.push_back( (FUNC_HELP)dlsym(handle, "Help") ); /获取ID函数地址 vecGetid.push_back( (FUNC_GETID)dlsym(handle, "GetID") ); +pluginCount; /获取用户输入的参数 if (argc > 1) char* param = argv1; if ( !strcmp(param,

20、"help") ) /用户输入的是help /循环,显示所有插件的功能ID和帮助信息 for (int i = 0; i < pluginCount; i+) cout << vecGetidi() << ": " /输出ID vecHelpi(); /调用帮助信息函数 else /用户可能输入的是功能ID int id = atoi(param); /循环,找出该功能 for (int i = 0; i < pluginCount; i+) if (vecGetidi() = id) /找到了 vecPrinti()

21、; /调用其打印函数 return 0;先编译测试程序编译插件1编译插件2将两个插件放入plugin目录测试帮助信息调用功能1调用功能2n 版本4要求:n 在版本3中,插件导出了Print、GetID、Help三个函数,主程序需要使用多个容器分别保存这些函数地址n 在复杂的业务逻辑中,导出的函数可能更多,若还按照版本3的方式,代码维护性不佳n 将三个导出函数都放在一个类中,让插件外部获取该类的对象思想:定义一个插件接口类,所有插件类继承自这个接口类,并覆盖其中的三个方法,然后动态链接库的导出函数,返回类型为父类指针类型,创建一个插件类对象,返回其指针即可。插件接口类代码,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; ;/获取插件接口对象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; ;/获取插件接口对象extern "C" CPluginInterface* getInterface() static Plugin plugin; return &plugin;插件文件搜索类的代码与上相同,省略。测试程序代码,test.cpp#inc

26、lude <dlfcn.h>#include <iostream>#include <string.h>#include <stdlib.h>#include "CPluginSeacher.h"#include "CPluginInterface.h"using namespace std;/导出函数的指针类型typedef CPluginInterface* (*FUNC_GETINTERFACE)();/主程序,测试代码int main (int argc, char *argv) /存放所有插件的文

27、件名 vector<string> vstrPluginNames; /定义插件搜索类对象 CPluginSeacher enumerator; /获取所有的插件文件名 if(!enumerator.GetPluginNames(vstrPluginNames) cout << "GetPluginNames error" << endl; return 0; int pluginCount = 0; vector<CPluginInterface*> vecPluginIfs; /遍历文件名数组,依次打开并获取导出的接口对象 for(int i = 0; i< vstrPluginNames.size(); i+) /打开动态链接库文件 void *handle = dlopen(vstrPluginNames

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论