最近研究了一下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
Copy 1
2
3
// device.cpp
#include "device.hpp"
PLUMA_PROVIDER_SOURCE(Device, 6, 3);
Copy 如上所示,是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 );
Copy 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 );
Copy 上面实现了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 ;
}
Copy 这里在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 ;
}
Copy 这里就是主要的调用逻辑了。官网中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
Copy 看下编译过程:
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
Copy 执行:
1
2
3
4
./main
size for providers are:2
keyboard
screen
Copy 以上就是实践的内容了。