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