Linux插件框架实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

电子科技大学
实验报告
学生姓名:学号:指导教师:
实验地点:A2-412 实验时间:2012.01.04
一、实验室名称:
Linux环境高级编程实验室
二、实验项目名称:
插件框架实验
三、实验学时:
4学时
四、实验目的:
学习和实践插件框架的开发。

理解插件的工作原理,为进一步开发高可用,高复杂度的插件打下基础。

五、实验内容:
1、使用动态链接库实现打印功能:
开发一个程序,向屏幕打印“Hello World”;在不重新编译链接原程序的前提下,将打印的文字改为“Hello China”。

2、使用动态链接库实现自定义打印功能:
同时要打印“Hello World”,打印“Hello China”,甚至同时打印未来才会增加的其他打印信息,打印信息的链接库放在一个固定目录中,遍历这个目录,获取所有动态链接库。

打印未来的这些信息,也不能重新编译链接原程序。

3、
1)通过命令行方式:./a.out help,输出所有插件实现的功能ID,以及该功能ID对应的功能描述。

2)通过命令行方式:./a.out FuncID,调用具体打印功能(每个插件导出GetID接口)。

4、将插件导出的Print、GetID、Help三个函数放在一个类中,主程序需要使用多个容器分别保存这些函数地址,让插件外部获取该类的对象。

综合练习:实现一个软件系统,该系统可对文件进行统计分析。

究竟对文件进行什么样的统计分析,最终用户自己也不是很清楚,目前只知道需要统计文件的行数。

也就是说,本软件系统将会随时面临,增加文件统计新功能的难题。

请结合本实验内容,设计并实现这样一个面向文件统计功能的插件系统。

(需要实现的插件包括:统计某个文件的行数,统计某个文件的字节数)
六、实验步骤:
程序1:
A.h:
extern "c" void f();
a2.cpp:
#include<iostream>
#include"a.h"
using namespace std;
void f()
{
cout << "hello,China!" << endl;
}
A1.cpp:
#include<iostream>
#include"a.h"
using namespace std;
void f()
{
cout << "Hello,Word" << endl;
}
Main.cpp:
#include"a.h"
#include<dlfcn.h>
#include<iostream>
using namespace std;
int main()
{
void *handle = dlopen("./libtest.so", RTLD_LAZY);
if(0 == handle)
{
cout << "dlopen error" << endl;
return 0;
}
typedef void (*Fun)();
Fun f1 = (Fun)dlsym(handle, "f");
if(0 == f1)
{
cout << "f1 error" << endl;
char *str = dlerror();
cout << str << endl;
}
(*f1)();
dlclose(handle);
return 0;
}
程序运行结果如图1所示:
图1:字符的变换程序2:
A1.cpp:
#include<iostream>
using namespace std;
extern"C" void f()
{
cout << "Hello world" << endl;
}
A2.cpp:
#include<iostream>
using namespace std;
extern "C" void f()
{
cout << "Hello,china!" << endl;
}
A3.cpp:
#include<iostream>
using namespace std;
extern "C" void f()
{
cout << "Hello 333" << endl;
}
A4.cpp:
#include<iostream>
using namespace std;
extern "C" void f()
{
cout << "Hello 4444" << endl;
}
Test2.cpp:
#include<dlfcn.h>
#include<iostream>
#include<dirent.h>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{
char path[260];
DIR *dir;
struct dirent *ptr;
dir=opendir("/root/test/test4/plug2/plugin/");
while((ptr=readdir(dir))!=NULL)
{
if ((strcmp(ptr->d_name,"..")==0)||(strcmp(ptr->d_name,".")==0))
{
continue;
}
sprintf(path,"/root/test/test4/plug2/plugin/%s", ptr->d_name);
void *handle = dlopen(path, RTLD_LAZY);
if(0 == handle)
{
cout << "dlopen error" << endl;
return 0;
}
typedef void (*Fun)();
Fun pf = (Fun)dlsym(handle, "f");
if(0 == pf)
{
cout << "pf error" << endl;
char *str = dlerror();
cout << str << endl;
return 0;
}
(*pf)();
dlclose(handle);
}
closedir(dir);
}
程序运行结果如图2所示:
图2:插件的遍历程序3:
a1.cpp:
#include <iostream>
using namespace std;
const int FUNC_ID = 1;
extern "C" void f()
{
cout << "Hello World!" << endl;
}
extern "C" void Help()
{
cout << "Function ID " << FUNC_ID << " : This function prints Hello World." << endl;
}
a2.cpp:
#include <iostream>
using namespace std;
const int FUNC_ID = 2;
extern "C" void f()
{
cout << "Hello China!" << endl;
}
extern "C" void Help()
{
cout << "Function ID " << FUNC_ID << " This function prints hello china." << endl;
}
CPluginEnumerator.cpp
#include "CPluginEnumerator.h"
#include <dirent.h>
#include <string.h>
#include <iostream>
#include <stdio.h>
CPluginEnumerator::CPluginEnumerator()
{
}
CPluginEnumerator::~CPluginEnumerator()
{
}
bool CPluginEnumerator::GetPluginNames(vector<string>& vstrPluginNames)
{
DIR *dir = opendir("/root/test/test4/plug3/plugin");
if(dir == 0)
return false;
for(;;)
{
struct dirent *ptr = readdir(dir);
if(ptr == 0)
break;
if((strcmp(ptr->d_name, ".") == 0)||(strcmp(ptr->d_name, "..") == 0)) continue;
char path[260];
sprintf(path, "/root/test/test4/plug3/plugin/%s", ptr->d_name);
vstrPluginNames.push_back(path);
}
closedir(dir);
return true;
}
Test.cpp:
#include <dlfcn.h>
#include <iostream>
#include "CPluginEnumerator.h"
#include <string.h>
#include <stdio.h>
using namespace std;
int main(int argc, char **argv)
{
char path [260];
if(argc != 2)
return 0;
if(strcmp(argv[1], "help") == 0)
{
vector<string> vstrPluginNames;
CPluginEnumerator enumerator;
if(!enumerator.GetPluginNames(vstrPluginNames))
{
cout << "GetPluginNames error" << endl;
return 0;
}
for(int i = 0; i< vstrPluginNames.size(); i++)
{
void *handle = dlopen(vstrPluginNames[i].c_str(), RTLD_LAZY);
if(handle == 0)
{
cout << "dlopen error" << endl;
return 0;
}
typedef void (*FUNC_HELP)();
FUNC_HELP dl_help = (FUNC_HELP)dlsym(handle, "Help");
if(dl_help == 0)
{
cout << "dlsym error" << endl;
return 0;
}
(dl_help)();
dlclose(handle);
}
}
else if(strcmp(argv[1], "1") == 0)
{
sprintf(path, "/root/test/test4/plug3/plugin/%s", "a1.so");
void *handle = dlopen(path, RTLD_LAZY);
if(handle == 0)
{
cout << "dlopen error" << endl;
return 0;
}
typedef void (*FUNC_PRINT)();
FUNC_PRINT dl_print = (FUNC_PRINT)dlsym(handle, "f");
if(dl_print == 0)
{
cout << "dlsym error" << endl;
return 0;
}
(dl_print)();
dlclose(handle);
}
else if(strcmp(argv[1], "2") == 0)// 得到第二个func的参数
{
sprintf(path, "/root/test/test4/plug3/plugin/%s", "a2.so");
void *handle = dlopen(path, RTLD_LAZY);
if(handle == 0)
{
cout << "dlopen error" << endl;
return 0;
}
typedef void (*FUNC_PRINT)();
FUNC_PRINT dl_print = (FUNC_PRINT)dlsym(handle, "f");
if(dl_print == 0)
{
cout << "dlsym error" << endl;
return 0;
}
(dl_print)();
dlclose(handle);
}
return 0;
}
程序运行结果如图3所示:
图3:插件输出
程序4:
CPluginEnumerator.h:
#ifndef CPLUGINENUMERATOR_H
#define CPLUGINENUMERATOR_H
#include <vector>
#include <string>
using namespace std;
class CPluginEnumerator
{
public:
CPluginEnumerator();
virtual ~CPluginEnumerator();
bool GetPluginNames(vector<string>& vstrPluginNames);
};
#endif
CPluginEnumerator.cpp:
#include "CPluginEnumerator.h"
#include <dirent.h>
#include <string.h>
CPluginEnumerator::CPluginEnumerator()
{
}
CPluginEnumerator::~CPluginEnumerator()
{
}
bool CPluginEnumerator::GetPluginNames(vector<string>& vstrPluginNames) {
DIR *dir = opendir("./plugin");
if(dir == 0)
return false;
for(;;)
{
struct dirent *pentry = readdir(dir);
if(pentry == 0)
break;
if(strcmp(pentry->d_name, ".") == 0)
continue;
if(strcmp(pentry->d_name, "..") == 0)
continue;
string str = "./plugin/";
str += pentry->d_name;
vstrPluginNames.push_back(str);
}
closedir(dir);
return true;
}
CPluginController.h
#ifndef CPLUGINCONTROLLER_H
#define CPLUGINCONTROLLER_H
#include <vector>
class IPrintPlugin;
class CPluginController
{
public:
CPluginController(void);
virtual ~CPluginController(void);
bool InitializeController(void);
bool UninitializeController(void);
bool ProcessHelp(void);
bool ProcessRequest(int FunctionID); private:
std::vector<void *> m_vhForPlugin;
std::vector<IPrintPlugin*> m_vpPlugin; };
#endif
CPluginController.cpp
#include "CPluginController.h"
#include "CPluginEnumerator.h"
#include "IPrintPlugin.h"
#include "dlfcn.h" CPluginController::CPluginController(void) {
}
CPluginController::~CPluginController(void)
{
}
bool CPluginController::InitializeController(void)
{
std::vector<std::string> vstrPluginNames;
CPluginEnumerator enumerator;
if(!enumerator.GetPluginNames(vstrPluginNames))
return false;
for(unsigned int i=0 ; i<vstrPluginNames.size(); i++)
{
typedef int (*PLUGIN_CREATE)(IPrintPlugin**);
PLUGIN_CREATE CreateProc;
IPrintPlugin *pPlugin = NULL;
void* hinstLib = dlopen(vstrPluginNames[i].c_str(), RTLD_LAZY);
if(hinstLib != NULL)
{
m_vhForPlugin.push_back(hinstLib);
CreateProc = (PLUGIN_CREATE)dlsym(hinstLib, "CreateObj");
if(NULL != CreateProc)
{
(CreateProc)(&pPlugin);
if(pPlugin != NULL)
{
m_vpPlugin.push_back(pPlugin);
}
}
}
}
return true;
}
bool CPluginController::ProcessRequest(int FunctionID)
for(unsigned int i = 0; i < m_vpPlugin.size(); i++)
{
if(m_vpPlugin[i]->GetID() == FunctionID)
{
m_vpPlugin[i]->Print();
break;
}
}
return true;
}
bool CPluginController::ProcessHelp(void)
{
std::vector<std::string> vstrPluginNames;
CPluginEnumerator enumerator;
if(!enumerator.GetPluginNames(vstrPluginNames))
return false;
for(unsigned int i=0 ; i<vstrPluginNames.size(); i++)
{
typedef int (*PLUGIN_CREATE)(IPrintPlugin**);
PLUGIN_CREATE CreateProc;
IPrintPlugin *pPlugin = NULL;
void* hinstLib = dlopen(vstrPluginNames[i].c_str(), RTLD_LAZY);
if(hinstLib != NULL)
{
CreateProc = (PLUGIN_CREATE)dlsym(hinstLib, "CreateObj");
if(NULL != CreateProc)
{
(CreateProc)(&pPlugin);
if(pPlugin != NULL)
{
pPlugin->Help();
}
}
dlclose(hinstLib);
}
}
return true;
}
bool CPluginController::UninitializeController()
{
for(unsigned int i = 0; i < m_vhForPlugin.size(); i++) {
dlclose(m_vhForPlugin[i]);
}
return true;
}
IPrintPlugin.h
#pragma once
class IPrintPlugin
{
public:
IPrintPlugin();
virtual ~IPrintPlugin();
virtual void Help() = 0;
virtual void Print() = 0;
virtual int GetID() = 0;
};
IPrintPlugin.cpp
#include "IPrintPlugin.h"
IPrintPlugin::IPrintPlugin()
{
}
IPrintPlugin::~IPrintPlugin()
{
}
Function.cpp
#include <iostream>
#include "IPrintPlugin.h"
using namespace std;
const int FUNC_ID = 1;
class CPrintPlugin : public IPrintPlugin
{
public:
CPrintPlugin()
{
}
virtual ~CPrintPlugin()
{
}
virtual void Print()
{
cout << "Hello World!" << endl;
}
virtual void Help()
{
cout << "Function ID " << FUNC_ID << " : This function will print hello world." << endl;
}
virtual int GetID(void)
{
return FUNC_ID;
}
};
extern "C" void CreateObj(IPrintPlugin **ppPlugin)
{
static CPrintPlugin plugin;
*ppPlugin = &plugin;
}
function1.cpp
#include <iostream>
#include "IPrintPlugin.h"
const int FUNC_ID = 2;
class CPrintPlugin : public IPrintPlugin
{
public:
CPrintPlugin()
{
}
virtual ~CPrintPlugin()
{
}
virtual void Print()
{
cout << "Hello China!" << endl;
}
virtual void Help()
{
cout << "Function ID " << FUNC_ID << " : This function will print hello china." << endl;
}
virtual int GetID(void)
{
return FUNC_ID;
}
};
extern "C" void CreateObj(IPrintPlugin **ppPlugin)
{
static CPrintPlugin plugin;
*ppPlugin = &plugin;
}
Main.cpp
#include <iostream>
#include "CPluginController.h"
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if(argc != 2)
{
cout << "Parameters error" << endl;
return 0;
}
if(strcmp(argv[1], "help") == 0)
{
CPluginController pc;
pc.ProcessHelp();
return 0;
}
int FunctionID = atoi(argv[1]);
CPluginController pc;
pc.InitializeController();
pc.ProcessRequest(FunctionID);
pc.UninitializeController();
return 0;
}
程序运行结果如图4所示:
图4:插件获取类对象
综合练习:
CPluginController.cpp
#include "CPluginController.h"
#include "CPluginEnumerator.h"
#include "IPrintPlugin.h"
#include "dlfcn.h"
#include <string.h>
CPluginController::CPluginController(void)
{
}
CPluginController::~CPluginController(void)
{
}
bool CPluginController::InitializeController(void)
{
std::vector<std::string> vstrPluginNames;
CPluginEnumerator enumerator;
if(!enumerator.GetPluginNames(vstrPluginNames))
return false;
for(unsigned int i=0 ; i<vstrPluginNames.size(); i++)
{
typedef int (*PLUGIN_CREATE)(IPrintPlugin**);
PLUGIN_CREATE CreateProc;
IPrintPlugin *pPlugin = NULL;
void* hinstLib = dlopen(vstrPluginNames[i].c_str(), RTLD_LAZY);
if(hinstLib != NULL)
{
m_vhForPlugin.push_back(hinstLib);
CreateProc = (PLUGIN_CREATE)dlsym(hinstLib, "CreateObj");
if(NULL != CreateProc)
{
(CreateProc)(&pPlugin);
if(pPlugin != NULL)
{
m_vpPlugin.push_back(pPlugin);
}
}
}
}
return true;
}
bool CPluginController::ProcessRequest(int FunctionID)
{
for(unsigned int i = 0; i < m_vpPlugin.size(); i++)
{
if(m_vpPlugin[i]->GetID() == FunctionID)
{
m_vpPlugin[i]->Print();
break;
}
}
return true;
}
bool CPluginController::ProcessHelp(void)
{
std::vector<std::string> vstrPluginNames;
CPluginEnumerator enumerator;
if(!enumerator.GetPluginNames(vstrPluginNames))
return false;
for(unsigned int i=0 ; i<vstrPluginNames.size(); i++)
{
typedef int (*PLUGIN_CREATE)(IPrintPlugin**);
PLUGIN_CREATE CreateProc;
IPrintPlugin *pPlugin = NULL;
void* hinstLib = dlopen(vstrPluginNames[i].c_str(), RTLD_LAZY);
if(hinstLib != NULL)
{
CreateProc = (PLUGIN_CREATE)dlsym(hinstLib, "CreateObj");
if(NULL != CreateProc)
{
(CreateProc)(&pPlugin);
if(pPlugin != NULL)
{
pPlugin->Help();
}
}
dlclose(hinstLib);
}
}
return true;
}
bool CPluginController::IfProcess(char *Function)//判断插件是否存在
{
unsigned int i;
for(i = 0; i < m_vpPlugin.size(); i++)
{
if(strcmp(Function, m_vpPlugin[i]->GetName()) == 0)
{
break;
}
};
if(i < m_vpPlugin.size())//插件存在
{
return true;
}
else
{
return false;
}
}
bool CPluginController::ProcessFunction(char *Function,char*Document)//执行插件功能
for(unsigned int i = 0; i < m_vpPlugin.size(); i++)
{
if(strcmp(Function, m_vpPlugin[i]->GetName()) == 0)
{
m_vpPlugin[i]->Fun(Document);//插件功能
break;
}
}
return true;
}
bool CPluginController::UninitializeController()
{
for(unsigned int i = 0; i < m_vhForPlugin.size(); i++)
{
dlclose(m_vhForPlugin[i]);
}
return true;
}
CPluginController.h
#ifndef CPLUGINCONTROLLER_H
#define CPLUGINCONTROLLER_H
#include <vector>
class IPrintPlugin;
class CPluginController
{
public:
CPluginController(void);
virtual ~CPluginController(void);
bool InitializeController(void);
bool UninitializeController(void);
bool ProcessHelp(void);
bool ProcessRequest(int FunctionID);
bool IfProcess(char *Function);
bool ProcessFunction(char *Function,char *Document);
private:
std::vector<void *> m_vhForPlugin;
std::vector<IPrintPlugin*> m_vpPlugin;
};
#endif
CPluginEnumerator.h
#ifndef CPLUGINENUMERATOR_H
#define CPLUGINENUMERATOR_H
#include <vector>
#include <string>
using namespace std;
class CPluginEnumerator
{
public:
CPluginEnumerator();
virtual ~CPluginEnumerator();
bool GetPluginNames(vector<string>& vstrPluginNames);
};
#endif
CPluginEnumerator.cpp
#include "CPluginEnumerator.h"
#include <dirent.h>
#include <string.h>
CPluginEnumerator::CPluginEnumerator()
{
}
CPluginEnumerator::~CPluginEnumerator()
{
}
bool CPluginEnumerator::GetPluginNames(vector<string>& vstrPluginNames) {
DIR *dir = opendir("./plugin");
if(dir == 0)
return false;
for(;;)
{
struct dirent *pentry = readdir(dir);
if(pentry == 0)
break;
if(strcmp(pentry->d_name, ".") == 0)
continue;
if(strcmp(pentry->d_name, "..") == 0)
continue;
string str = "./plugin/";
str += pentry->d_name;
vstrPluginNames.push_back(str);
}
closedir(dir);
return true;
}
Main.cpp
#include <iostream>
#include "CPluginController.h"
#include <string.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char **argv)
{
if(argc == 2)
{
if(strcmp(argv[1], "help") == 0)//帮助功能
{
CPluginController pc;
pc.ProcessHelp();
return 0;
}
else
{
int FunctionID = atoi(argv[1]);
CPluginController pc;
pc.InitializeController();
pc.ProcessRequest(FunctionID);
pc.UninitializeController();
return 0;
}
}
else if(argc == 3)
{
CPluginController pc;
char *Function = argv[1];
// Function+=".so";
char *Document = argv[2];//操作的文件名
pc.InitializeController();
if(pc.IfProcess(Function)==false)//判断插件是否存在
{
cout << "No this plugin!" << endl;
}
else//
{
pc.ProcessFunction(Function,Document);
};
pc.UninitializeController();
return 0;
}
else
{
cout << "Parameters error" << endl;
return 0;
}
}
插件:
IPrintPlugin.cpp
#include "IPrintPlugin.h"
IPrintPlugin::IPrintPlugin()
{
}
IPrintPlugin::~IPrintPlugin()
{
}
IPrintPlugin.h
#pragma once
class IPrintPlugin
{
public:
IPrintPlugin();
virtual ~IPrintPlugin();
virtual void Help() = 0;
virtual void Print() = 0;
virtual int GetID() = 0;
virtual char * GetName() = 0;//添加部分virtual void Fun(char*) = 0;
};
Line.cpp
#include <iostream>
#include "IPrintPlugin.h"
#include <unistd.h>//read(file)
#include <fcntl.h>
#include <string.h>
using namespace std;
const int FUNC_ID = 3;
char FUNC_NAME[]="sl";//statistics line! class CPrintPlugin : public IPrintPlugin {
public:
CPrintPlugin()
{
}
virtual ~CPrintPlugin()
}
virtual void Print()
{
cout << "Statistics the document line!" << endl;
}
virtual void Help()
{
cout << "Function ID " << FUNC_ID << " : This function will statistics the document line." << endl;
}
virtual int GetID(void)
{
return FUNC_ID;
}
virtual char *GetName()
{
return FUNC_NAME;
}
virtual void Fun(char *Document)
{
int fp;
char temp;
long num=0;//统计
//open file
if((fp=open(Document,O_RDONLY))==-1)
{
cout<<"Can not open: "<<Document<<endl;
return ;
};
while(read(fp,&temp,1))
{
if(temp=='\n')
{
num++;
}
};
close(fp);
cout<<Document<<" lines is :"<<num<<endl;
};
extern "C" void CreateObj(IPrintPlugin **ppPlugin)
{
static CPrintPlugin plugin;
*ppPlugin = &plugin;
}
Words.cpp
#include <iostream>
#include "IPrintPlugin.h"
#include <unistd.h>//read(file)
#include <fcntl.h>
using namespace std;
const int FUNC_ID = 4;
char FUNC_NAME[]="sw";//statistics words
class CPrintPlugin : public IPrintPlugin
{
public:
CPrintPlugin()
{
}
virtual ~CPrintPlugin()
{
}
virtual void Print()
{
cout << "statistics the document words!" << endl;
}
virtual void Help()
{
cout << "Function ID " << FUNC_ID << " : This function will statistics the document words." << endl;
}
virtual int GetID(void)
return FUNC_ID;
}
virtual char *GetName()
{
return FUNC_NAME;
}
virtual void Fun(char *Document)
{
int fp;
char temp;
long num=0;//统计
//open file
if((fp=open(Document,O_RDONLY))==-1)
{
cout<<"Can not open: "<<Document<<endl;
return ;
};
while(read(fp,&temp,1))
{
num++;
};
close(fp);
if(num==0)
{
cout<<"Empty file: "<<Document<<endl;
return ;
};
cout<<Document<<"words is :"<<num<<endl;
};
};
extern "C" void CreateObj(IPrintPlugin **ppPlugin) {
static CPrintPlugin plugin;
*ppPlugin = &plugin;
}
程序运行结果如图5所示:
图5:插件获取类对象
七、总结及心得体会:
本次试验了解并大致掌握了linux下插件开发的多种方法,尤其是综合试验中,对于插件的安装。

这将很好的为以后的编程学习提供帮助。

此外本次试验让我懂得了:耐心就会有结果!
八、对本实验过程及方法、手段的改进建议:
本次综合实验已经能够动态装、卸插件基本符合实际应用。

以后的开发中应能用插件获取主体程序中的功能并修改。

报告评分:
指导教师签字:。

相关文档
最新文档