C++ component framework.
kshell
is a component(DLL or SO) loader and container, the loaded component should offer specific export function.
Component is called Bundle in kshell
, bundle could be loaded as a loadable object, Windows DLL or Linux SO file, loadable object should offer three export function and a configuration file (named meta.inf).
- newActivator
Fork and return a activator. - newService
Fork and return a service - destroyService
destroy service
The prototype of export functions:
BundleFunc void* newActivator();
BundleFunc void* newService(const char* name);
BundleFunc void* destroyService(void* service, const char* name);
The name of three export function are configurable in meta.inf, the naming convension is same as C/C++ function naming guide.
Activator gives bundle a chance to custimize steps of startup and cleanup, developer could write code to define the activator's behavior, below is the activator interface:
class BundleActivator {
public:
virtual ~BundleActivator() {}
virtual void start(BundleContext* context) throw(BundleException) = 0;
virtual void stop(BundleContext* context) throw(BundleException) = 0;
};
Bundle holds multiple services, each service implements specified interface, the interface is the basic unit of service to provide services for other bundle's service.
newService
fork a new service instance, destroyService
destroy service instance.
bundle="caller_bundle"
version="0.1"
symbolicName="caller"
activator="newActivator"
newService="newService"
destroyService="destroyService"
require="mybundle"
- bundle
Loadable object name - version
Bundle version - symbolicName
The name referred by other service - activator
The export function name of activator - newService
The export function name of forking new service instance - destroyService
The export function name of destroying service instance - require
Bundle dependency(format: bundle-name;bundle-name;...)
See bundle-sample.
There are two bundle in example:my_bundle
and caller_bundle
,my_bundle
exports a very simple service MyService
:
class MyService {
public:
virtual ~MyService() {}
virtual const std::string& getGreeting() const = 0;
};
caller_bundle
fork a MyService
service in startup phase of activator:
void BundleActivator_CallerBundle::start(BundleContext* context) throw(BundleException) {
_context = context;
// fork a 'MyService' and call it
AutoService<MyService> myService = loadClass<MyService>(_context, "mybundle", "myservice");
if (!myService) {
std::cout << "create service 'myservice' failed" << std::endl;
}
std::cout << "call MyService::getGreeting(): " << myService->getGreeting() << std::endl;
// destroy 'MyService'
myService.destroy();
}
After `kshell` started the console output like below,for now, the `kshell` start as debug mode:
Debugging kshell.
kshell v.1.0.0
Root -> [E:\kshell-git\kshell\win-proj\$\..\..\bin\debug]
Check bundle dependency -> [Resolved]
Install Bundle -> [mybundle] -> [INSTALLED]
Install Bundle -> [caller ]call MyService::getGreeting(): hi caller!
-> [INSTALLED]
- Debug mode
- Daemon mode(Service mode)
kshell -install to install the service(Windows ONLY)
kshell -start to start the service
kshell -stop to start the service
kshell -remove to remove the service(Windows ONLY)
kshell -debug to run as a console app for debugging
-debug
make kshell
start as debug mode and print information on screen. On Windows:
kshell -install
kshell
will be installed as a Windows service(make sure you have proper operation priviledge),kshell
on Linux cannot be installed as a service.
kshell -remove
Remove kshell
from service list,kshell
on Linux cannot be removed.
kshell -start
Start kshell
service,On Linux, kshell
will run as a daemon process,Windows as Windows service.
kshell -stop
Shutdown kshell
service.
When kshell
starting it will scan the bundle/ directory and parse bundle's meta.inf
, sort the dependency of bundles via requrie
attribute, kshell
will stop when bundle not there or circular dependency exist, if everything is ok kshell
will load bundle one by one and invoke start
method of bundle's activator.
kshell
invoke the stop
method of bundle's activator by inverted sequence of dependency and unload loadable object(DLL or SO).
C++组件框架.
kshell
是组件(DLL或者SO)的加载运行容器,组件需要预先提供特定的导出函数,才能被容器加载。
组件在kshell
内被称为Bundle,每个bundle都作为可加载对象存在,在Windows下为DLL文件,Linux下为SO文件,可加载对象需要提供
3个导出函数及一个配置文件(名为meta.inf).
- newActivator
建立并返回组件激活器 - newService
建立并返回一个服务 - destroyService
销毁服务
导出函数的原型为:
BundleFunc void* newActivator();
BundleFunc void* newService(const char* name);
BundleFunc void* destroyService(void* service, const char* name);
以上3个导出函数的名称可以配置在meta.inf文件内,函数名称只要符合C/C++函数命名规范即可。
激活器为组件提供了在启动和停止阶段的自定义操作的机会,用户可以在激活器内提供自己组件需要的操作,激活器接口定义为:
class BundleActivator {
public:
virtual ~BundleActivator() {}
virtual void start(BundleContext* context) throw(BundleException) = 0;
virtual void stop(BundleContext* context) throw(BundleException) = 0;
};
组件可以建立多个服务,每个服务都是实现了特定的接口,服务以接口为单位为其他组件内的服务提供具体功能。
通过导出函数newService
产生组件内的某个服务实例,通过destroyService
销毁某个服务实例。
bundle="caller_bundle"
version="0.1"
symbolicName="caller"
activator="newActivator"
newService="newService"
destroyService="destroyService"
require="mybundle"
- bundle
组件的可加载对象的名称 - version
组件版本 - symbolicName
组件被其他组件访问时的名字 - activator
激活器导出函数名称 - newService
服务产生函数名称 - destroyService
服务销毁函数名称 - require
依赖的其他组件(格式为组件名;组件名;...)
参见bundle-sample.
例子中提供了两个组件:my_bundle
和caller_bundle
,my_bundle
内提供了一个非常简单的服务MyService
:
class MyService {
public:
virtual ~MyService() {}
virtual const std::string& getGreeting() const = 0;
};
caller_bundle
在激活器启动阶段建立并使用了MyService
服务:
void BundleActivator_CallerBundle::start(BundleContext* context) throw(BundleException) {
_context = context;
// fork a 'MyService' and call it
AutoService<MyService> myService = loadClass<MyService>(_context, "mybundle", "myservice");
if (!myService) {
std::cout << "create service 'myservice' failed" << std::endl;
}
std::cout << "call MyService::getGreeting(): " << myService->getGreeting() << std::endl;
// destroy 'MyService'
myService.destroy();
}
启动`kshell`后将得到如下输出,当前kshell以调试模式启动:
Debugging kshell.
kshell v.1.0.0
Root -> [E:\kshell-git\kshell\win-proj\$\..\..\bin\debug]
Check bundle dependency -> [Resolved]
Install Bundle -> [mybundle] -> [INSTALLED]
Install Bundle -> [caller ]call MyService::getGreeting(): hi caller!
-> [INSTALLED]
- 调试模式
- 后台模式
kshell -install to install the service(Windows ONLY)
kshell -start to start the service
kshell -stop to start the service
kshell -remove to remove the service(Windows ONLY)
kshell -debug to run as a console app for debugging
-debug
将kshell
以调试模式启动并使用屏幕作为输出. 在Windows系统下,可以通过:
kshell -install
将kshell安装为Windows服务(确保拥有相应的操作权限),Linux系统下暂时未提供此功能,通过:
kshell -remove
将kshell
服务卸载,Linux系统暂时未提供此功能。 可以通过命令:
kshell -start
启动kshell
服务,在Linux下kshell
将以后台进程方式运行,Windows下将以Windows服务运行,可以通过:
kshell -stop
关闭kshell
服务.
kshell
启动后会自动扫描当前目录下的bundle/目录并解析所有组件的配置文件,通过配置文件内的require
字段排序组件之间的依赖关系,如果所依赖的组件或者组件有环形的相互依赖关系则停止并报错,如果一切都是正确的,那么kshell
会按照排序后的顺序逐个加载组件并调用激活器的start
方法.
kshell
按组件依赖关系的逆序逐个调用激活器的stop
方法并卸载可加载对象(DLL或SO).