本文描述小鸡射手采用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"

class TEST_Export TestDynamic : public ACE_Service_Object, public ITimerListener

...{
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"

int TestDynamic::init (int argc, ACE_TCHAR *argv[])

...{
ACE_DEBUG ((LM_DEBUG, "Initializing... "));
// 读取配置文件中的配置
ACE_Get_Opt opt(argc, argv, "s:p:", 0);

for(int c; (c=opt()) != -1; ) ...{

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;
}

int TestDynamic::fini (void)

...{
ACE_DEBUG ((LM_DEBUG, "Finishing... "));
return 0;
}

int TestDynamic::info(ACE_TCHAR **str, size_t len) const

...{

static char info[512] = ...{0};
sprintf(info, "test dynamic.");
*str = info;
return strlen(info);
}

void TestDynamic::OnTimer(const int eventID, const void* data)

...{
ACE_DEBUG ((LM_DEBUG, "TimerID is %d ", eventID));
}

// 采用宏定义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"

template <class DLL_SERVICE_TYPE>
class DynamicService

...{
public:
static DLL_SERVICE_TYPE* Instance(const char* const name)

...{
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等。