本文描述小鸡射手采用ACE的Service Configurator Framework实现C++的plugin机制。
首先,定义一个export头文件,可以从/examples/APG/Svc_Config的HASTATUS_export.h复制修改。头文件定义如下:
#include
"
ace/OS.h
"
#include
"
ace/Service_Object.h
"
#include
"
TEST_export.h
"
#include
"
ITimerListener.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
class
TEST_Export TestDynamic :
public
ACE_Service_Object,
public
ITimerListener
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public:
virtual int init (int argc, ACE_TCHAR *argv[]);
virtual int fini (void);
virtual int info (ACE_TCHAR **str, size_t len) const;
virtual void OnTimer(const int eventID, const void* data);
}
;
OnTimer是ITimerListener中定义的一个业务函数。TestDynamic类的实现如下:
#include
"
ace/Get_Opt.h
"
#include
"
Test_Dynamic.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
TestDynamic::init (
int
argc, ACE_TCHAR
*
argv[])
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
ACE_DEBUG ((LM_DEBUG, "Initializing... "));
// 读取配置文件中的配置
ACE_Get_Opt opt(argc, argv, "s:p:", 0);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(int c; (c=opt()) != -1; ) ...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
switch(c) ...{
case 's' :
ACE_DEBUG((LM_DEBUG, "Server is %s. ", opt.opt_arg()));
break;
case 'p':
ACE_DEBUG((LM_DEBUG, "Port is %d. ", atoi(opt.opt_arg())));
break;
}
}
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
TestDynamic::fini (
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
ACE_DEBUG ((LM_DEBUG, "Finishing... "));
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
TestDynamic::info(ACE_TCHAR
**
str, size_t len)
const
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
static char info[512] = ...{0};
sprintf(info, "test dynamic.");
*str = info;
return strlen(info);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
TestDynamic::OnTimer(
const
int
eventID,
const
void
*
data)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
ACE_DEBUG ((LM_DEBUG, "TimerID is %d ", eventID));
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
采用宏定义Plugin
ACE_FACTORY_DEFINE (TEST, TestDynamic)
在VC中编译的话,注意增加预编译定义TEST_BUILD_DLL,并将RTTI打开。Plugin DLL就定义好了,配置文件svc.conf定义如下:
dynamic Test_Dynamic_Service Service_Object
*
TestDynamic:_make_TestDynamic()
"
-s 127.0.0.1 -p 8018
"
在给出主程序前,先定义根据服务名得到plugin实例的help函数,定义如下:
#include
"
ace/Service_Repository.h
"
#include
"
ace/Service_Types.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
template
<
class
DLL_SERVICE_TYPE
>
class
DynamicService
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public:
static DLL_SERVICE_TYPE* Instance(const char* const name)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
const ACE_Service_Type *svc_rec = 0;
if (ACE_Service_Repository::instance()->find(name, &svc_rec) == -1) return 0;
const ACE_Service_Type_Impl* type = svc_rec->type();
if (type == 0) return 0;
ACE_Service_Object* obj = ACE_static_cast(ACE_Service_Object*, type->object());
return ACE_dynamic_cast(DLL_SERVICE_TYPE*, obj);
}
}
;
调用的主程序就非常简单:
ACE_Service_Config::open(
"
Utility
"
);
ITimerListener
*
service
=
DynamicService
<
ITimerListener
>
::Instance(
"
Test_Dynamic_Service
"
);
service
->
OnTimer(
4
,
0
);
ACE的Service Configurator Framework的功能很强大,支持plugin service的动态load、unload等。