接着学习 Application 框架。我们一般的应用程序都会有提供的几个参数。-h, –help, -v –version, –daemon。下面我们就介绍下这些功能的实现。
Application 提供了一个 defineOptions( OptionSet & option ) 的方法。一个派生类想要支持命令行参数必须重载此方法,并且调用基类的此方法。
惨数:OptionSet 只是Option 类的一个 vector。Poco::Util::Option
这个类帮助我们在启动应用程序的时候添加一些启动参数。而 OptionSet 是存放了多个Option 的一个 vector。
来个简单的例子代码介绍其功能,具体的细节直接查看头文件Option.h 或者参考Poco::Util::ServerApplication 框架的实现。
/*
* main.cpp
*
* Created on: 2015年2月8日
* Author: yuhaiyang
*/
#include "Poco/Poco.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
using namespace Poco;
class MyApplication : public Util::Application
{
public:
MyApplication( )
{
m_helpRequested = false ;
}
void initialize( Application& self );
void uninitialize( );
void defineOptions( Util::OptionSet& options);
void handleHelp(const std::string& name, const std::string& value );
void handleDaemon(const std::string& name, const std::string& value);
int main(const std::vector<std::string>& args);
private:
bool m_helpRequested;//如果传参数进来那么此变量变为 true 在main() 方法就不要做其他的事情直接退出。
void beDaemon( );
};
void MyApplication::initialize( Application& self )
{
Util::Application::initialize( self );//帮我们初始化子系统,必须显示的调用。
std::cout << "this is initialize\n";
}
void MyApplication::uninitialize( )
{
Util::Application::uninitialize( );//帮我们关闭子系统,必须显示的调用。
std::cout << "this is uninitialize\n";
}
void MyApplication::defineOptions( Util::OptionSet& options)
{
Util::Application::defineOptions( options );//必须调用
std::cout << "defineOptions被调用" << std::endl;
options.addOption(
Util::Option("help", "h",
"display help information on command line arguments")
.required(false)
.repeatable(false)
.callback(Util::OptionCallback < MyApplication >(this, &MyApplication::handleHelp)) );
options.addOption(
Util::Option("daemon", "", "Run application as a daemon.")
.required(false)
.repeatable(false)
.callback(Util::OptionCallback<MyApplication>(this, &MyApplication::handleDaemon)) );
}
void MyApplication::handleHelp(const std::string& name, const std::string& value )
{
m_helpRequested = true;
Poco::Util::HelpFormatter helpFormatter( options() );
helpFormatter.format(std::cout);
}
void MyApplication::handleDaemon(const std::string& name, const std::string& value)
{
beDaemon();
}
void MyApplication::beDaemon()
{
pid_t pid;
if ((pid = fork()) < 0)
throw SystemException("cannot fork daemon process");
else if (pid != 0)
exit(0);
setsid();
umask(0);
FILE* fin = freopen("/dev/null", "r+", stdin);
if (!fin) throw Poco::OpenFileException("Cannot attach stdin to /dev/null");
FILE* fout = freopen("/dev/null", "r+", stdout);
if (!fout) throw Poco::OpenFileException("Cannot attach stdout to /dev/null");
FILE* ferr = freopen("/dev/null", "r+", stderr);
if (!ferr) throw Poco::OpenFileException("Cannot attach stderr to /dev/null");
}
int MyApplication::main(const std::vector<std::string>& args)
{
if( !m_helpRequested )
{
std::cout << "this is main no help\n";
while(1)
{
std::cout << "hello world" << std::endl;
sleep( 3 );
}
}else
{
std::cout <<"this is main call help\n";
}
return Application::EXIT_OK;
}
///主函数
//
int main( int argc , char **argv )
{
try
{
MyApplication app;
app.init( argc, argv );//在这里传主函数参数。
app.run( );
}catch( Poco::Exception &e )
{
std::cerr << "some error: " << e.what() << std::endl;
}
}
执行结果:
直接执行没有参数 ./a.out
结果:
defineOptions被调用
this is initialize
this is main no help
hello world
带参数执行,打印help 信息。 ./PocoOption -h
结果:
defineOptions被调用
usage:
-h, –help display help information on command line arguments
–daemon Run application as a daemon.
this is initialize
this is main call help
this is uninitialize
带参数执行,到后台 ./PocoOption –daemon
结果:
defineOptions被调用
ps aux | grep Poco
进程已经到后台成为守护进程。
yuhaiya+ 6442 0.0 0.0 30468 1032 ? Ss 17:19 0:00 ./PocoOption –daemon
总结:
很明显 Application 会调用 defineOptions() 方法。在执行的时候记加入参数,那么我们就 Application 会帮我们调用 defineOptions( Util::OptionSet& options)
添加指令的时候注册的对应函数。