最近研究了一下pluma的使用。发现官网上的简单示例对于刚入门的人来说还是麻烦了些(而且还有语法错误)。
下面重新整理了一个例子,作为备注。
其中,device
为一个虚基类,作为接口类存在。keyboard
及screen
作为实现了device的子类存在,实现具体的操作。在pluma上注册后,在main
中调用接口,实现keyboard
及screen
的调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
| // device.hpp
#ifndef _DEVICE_HPP_
#define _DEVICE_HPP_
#include "Pluma/Pluma.hpp"
class Device{
public:
virtual std::string getDescription() const=0;
};
// create DevicedProvider class
PLUMA_PROVIDER_HEADER(Device);
#endif
|
1
2
3
| // device.cpp
#include "device.hpp"
PLUMA_PROVIDER_SOURCE(Device, 6, 3);
|
如上所示,是device
的定义。其中PLUMA_PROVIDER_HEADER
和PLUMA_PROVIDER_SOURCE
pluma
提供的宏。功能暂且不论。我们继续往下看。
1
2
3
4
5
6
7
8
9
10
11
12
| // screen.hpp
#include "Pluma/Pluma.hpp"
#include "device.hpp"
class Screen: public Device{
public:
std:: string getDescription() const{
return "screen";
}
};
PLUMA_INHERIT_PROVIDER(Screen, Device);
|
1
2
3
4
5
6
7
8
9
10
11
12
| // keyboard.hpp
#include "Pluma/Pluma.hpp"
#include "device.hpp"
class Keyboard: public Device{
public:
std:: string getDescription() const{
return "keyboard";
}
};
PLUMA_INHERIT_PROVIDER(Keyboard, Device);
|
上面实现了screen
及keyboard
的逻辑。实现了之后,需要进行注册:
1
2
3
4
5
6
7
8
9
10
11
12
| // connect.cpp
#include <Pluma/Connector.hpp>
#include "keyboard.hpp"
#include "screen.hpp"
PLUMA_CONNECTOR
bool connect(pluma::Host& host){
// add a keyboard provider to host
host.add( new KeyboardProvider() );
host.add( new ScreenProvider() );
return true;
}
|
这里在connect
中进行了两个子类的注册。之所以使用connect
是因为后面的pluma使用的时候,官网给出的示例代码中,会从connect
入口开始调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // main.cpp
#include "Pluma/Pluma.hpp"
#include "device.hpp"
#include <iostream>
#include <vector>
int main()
{
pluma:: Pluma plugins;
plugins.acceptProviderType<DeviceProvider>();
plugins.load("./plugin/connect.so");
//plugins.load("./plugin/keyboard.so");
std::vector<DeviceProvider*> providers;
plugins.getProviders(providers);
std::cout<<"size for providers are:" << providers.size()<< std:: endl;
if (!providers.empty()){
for (std::vector<DeviceProvider*>::iterator device=providers.begin();
device != providers.end(); ++ device){
Device* myDevice = (*device)->create();
std::cout << myDevice->getDescription() << std::endl;
delete myDevice;
}
}
return 0;
}
|
这里就是主要的调用逻辑了。官网中myDevice
附近的拼写有主意,这是个坑了。
这里回顾下目录结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| .
├── connect.cpp
├── device.hpp
├── device.cpp
├── keyboard.hpp
├── main.cpp
├── plugin # 用来存储插件结果的目录
├── Pluma # 为了方便,这里将Pluma的include及src文件均拷贝到这里
│ ├── Config.hpp
│ ├── Connector.hpp
│ ├── Dir.cpp
│ ├── Dir.hpp
│ ├── DLibrary.cpp
│ ├── DLibrary.hpp
│ ├── Host.cpp
│ ├── Host.hpp
│ ├── PluginManager.cpp
│ ├── PluginManager.hpp
│ ├── Pluma.hpp
│ ├── Pluma.inl
│ ├── Provider.cpp
│ ├── Provider.hpp
│ └── uce-dirent.h
└── screen.hpp
|
看下编译过程:
1
2
3
4
5
| # 生成device.so
g++ connect.cpp device.cpp Pluma/*.cpp -shared -fPIC -o plugin/connect.so -I./
# 生成main
g++ main.cpp device.hpp device.cpp Pluma/*.cpp -o main -I./ -ldl
|
执行:
1
2
3
4
| ./main
size for providers are:2
keyboard
screen
|
以上就是实践的内容了。