できるだけシンプルに
一連の変更後”
Bjarne Stroustrup-プログラマ、C ++の作成者
前文
この記事では、Habrでほとんど取り上げられていない、かなり人気のあるPortable Componentsライブラリー(POCOと略記)についてお話したいと思います。 ソフトウェア製品のビジネスロジックの開発者にとっても、ほとんどの適用された問題の解決においても役立ちます。 C ++のクロスプラットフォームライブラリが豊富にあるため、POCOに直面する人が増え、どこから始めればいいのかわからなくなります。 この記事では、ライブラリに固有のテクノロジーを説明し、いくつかの問題を解決する簡単な例を示します。 また、このライブラリには、オープンソースプロジェクトと商用プロジェクトの両方で多くの成功が収められています。
説明
POCOは、ソフトウェア製品の開発、デバッグ、およびテストのプロセスを簡素化するクラスのコレクションです。 このライブラリは、接続性が低いモジュラーシステムの原理に基づいています。 彼女の同僚であるBoostと同様に、POCOはモジュールに分割され、各モジュールはシステムでその役割を果たしますが、Boostのような一般化されたプログラミングパラダイムほど
POCOは主にネットワーク開発に焦点を当てており、 Windows、Unix、Linux、eLinux、Mac OS X、Solaris、QNX Neutrino、Vxworks、Openvms、Tru64、HP-UX、Androidなどの一般的なオペレーティングシステムに移植されています。 プラットフォーム依存モジュールはすべてロジックから分離されているため、このリストは非常に急速に拡大しています。 実際、POCOは、C ++言語用の最新のコンパイラーがあるオペレーティングシステムに移植できます。
ライブラリは、サーバーまたはクライアント用のソフトウェアであるかどうかにかかわらず、開発の基礎として適用できますが、アプリケーションは使用可能なアーキテクチャのいずれかで実行されることが保証されます(特別な魔法がない場合もあります)。 さらに、POCOにはTCP Server Framework、Reactor Frameworkなどの強力なツールがあり、高性能のWEBサーバーを非常に簡単に作成できるため、開発時間を節約できます。 また、ライブラリには、コンソールアプリケーション、Unixデーモン、Windowsサービスを作成するためのスナップインがあります。 Qt、wxWidget、GTK +などのライブラリとの並行作業が可能です。
ライブラリの一部の概念は、 Javaクラスライブラリ、MS .NET Framework、およびApple Cocoaから借用しています 。 これらは主に、フロー制御やタイマーなどの高レベルのものです。
Pocoは、標準C ++およびSTLライブラリを使用して、 ANSI / ISO C ++ 2003言語標準に厳密に準拠して作成されています。 Boost Software Licenseの下で利用でき、商用および非商用の両方の使用が可能です。
POCOの学習方法
- プロジェクトウェブサイトで技術の説明を含むプレゼンテーションを勉強すること。
- ライブラリの最新バージョンをダウンロードする
- ライブラリとそのサンプルを作成する
- POCO SDKリファレンスで資料を調べる
- コミュニティを読む
ほとんどの例は、ソースコード、SDKリファレンス、およびプレゼンテーションにあります。
基本モジュールと使用例
ライブラリコア
- 動的データ型指定ツールAnyおよびDynamicAny
DynamicAny any("99"); int i = any; // i == 99 any = 65536; string s = any; // s == "65536" char c = any; // , RangeException
- 時刻と日付の操作
const char *date = "05.06.1977"; //Apple 2 birthday int Diff; DateTime time = DateTimeParser::parse("%d.%m.%Y", date, Diff); Timespan diff = DateTime() - time; cout << "Apple 2 " << diff.days() << " " << DateTimeFormatter::format(time, "%e %B %Y, %W", Diff) << endl; // : "5 June 1977, Sunday" cout << " " << (DateTime::isLeapYear(time.year()) ? "" : " ");
- イベントおよびアラートツール
#include "Poco/BasicEvent.h" #include "Poco/Delegate.h" #include <iostream> using BasicEvent; using Delegate; class Source { public: BasicEvent<int> theEvent; void fireEvent(int n) { theEvent(this, n); } }; class Target { public: void onEvent(const void* pSender, int& arg) { cout << "onEvent: " << arg << endl; } }; int main(int argc, char** argv) { Source source; Target target; // Event' source.theEvent += Delegate<Target, int>( &target, &Target::onEvent); // source.fireEvent(42); // source.theEvent -= Delegate<Target, int>( &target, &Target::onEvent); return 0; }
- 正規表現処理
RegularExpression regular("([0-9]+) ([0-9]+)"); vector<string> arr; regular.split("123 456", 0, arr); //arr = {“123 456”, ”123”, ”456”} string s = "123 456"; regular.subst(s, "$2 $1"); // s == "456 123"
- ダイナミックリンクライブラリを操作するためのツール。
SharedLibrary lib("C:\\Windows\\System32\\shell32.dll"); if (lib.isLoaded() && lib.hasSymbol("Control_RunDLL")) { auto fun = static_cast<void (*)()>(lib.getSymbol("Control_RunDLL")); fun(); // lib.unload(); }
- メモリ管理ツール
// class A {}; class B : public A {} ; class C : public A {}; … SharedPtr<A> pA; SharedPtr<B> pB(new B); pA = pB; // , B A pA = new B; // // pB = pA; // , SharedPtr pB = pA.cast<B>(); // SharedPtr<C> pC(new C); pB = pC.cast<B>(); // pB null // DynamicFactory<A> factory; factory.registerClass<B>("B"); // Instantiator<B, A> factory.registerClass<C>("C"); // Instantiator<C, A> SharedPtr<A> pA = factory.createInstance("B"); SharedPtr<A> pB = factory.createInstance("C"); factory.unregisterClass("C"); bool isA = factory.isClass("B"), // true isB = factory.isClass("C"), // false ( ) isC = factory.isClass("habrahabr"); // false ( ?!) // Buffer<char> buffer(1024); // 1024 cin.read(buffer.begin(), buffer.size()); // 1024 stdin streamsize n = cin.gcount(); string s(buffer.begin(), n); // cout << s << endl; // // MemoryPool pool(1024); // 1024 // MemoryPool pool(1024, 4, 16); // 16 ; 4 char* buffer = static_cast<char*>(pool.get()); // cin.read(buffer, pool.blockSize()); // stdin streamsize n = cin.gcount(); string s(buffer, n); // pool.release(buffer); // cout << s << endl; //
- シングルトン
class Singleton { public: int add(int i, int p) { return i+p; } static Singleton& instance() { static SingletonHolder<Singleton> single; return *single.get(); } }; … int res = Singleton::instance().add(1,2);
- 文字列フォーマッター
//printf-style formating string str = format("In %[0]d was %[1]s of %[2]s %[3]d", DateTime(1977,6,5).year(), // %[0]d string("b-day"), // %[1]s string("Apple"), // %[2]s 2); // %[3]d //str = “In 1977 was b-day of Apple 2”
- システム情報と環境変数の使用
cout << " : " << Environment::osName() << "\n : " << Environment::osVersion() << "\n: " << Environment::osArchitecture() << "\n. : " << Environment::nodeName() << "\nMAC-: " << Environment::nodeId(); if (Environment::has("HOME")) cout << "\n .: " << Environment::get("HOME") << endl; Environment::set("POCO", "foo"); // POCO=foo
データ圧縮
- ストリーミングデータ圧縮を実装するためのツール
- ZIPファイルを作成するためのツール
ofstream zipper("text.gz", ios::binary); ofstream text("text.txt", ios::binary); text << "Hello my little computer world. I can zip this string. It's wonderful."; text.close(); Zip::Compress zipc(zipper,true); zipc.addFile (Path("text.txt"), "text.txt"); zipc.close(); ifstream dezipper("text.gz", ios::binary); poco_assert (dezipper); Zip::Decompress zipd(dezipper,Path().append("\\text.dz")); zipd.decompressAllFiles();
暗号化
- 擬似乱数ジェネレータ
Random rnd; rnd.seed(); cout << ": " << rnd.next() << "\n: " << rnd.next(10) << "\n: " << rnd.nextChar() << "\n: " << rnd.nextBool() << "\n . : " << rnd.nextDouble(); RandomInputStream ri; string rs; ri >> rs;
- ハッシュを作成するメカニズム
string message(" "); string passphrase("anl!sfsd9!_3g2g?f73"); // //HMAC = Hash-based message authentication code ;) HMACEngine<SHA1Engine> encoder(passphrase); encoder.update(message); // // encoder.digest() string encodedstr(DigestEngine::digestToHex(encoder.digest())); // MD5 MD5Engine md5; DigestOutputStream ostr(md5); ostr << " "; ostr.flush(); // HEX string result = DigestEngine::digestToHex(md5.digest());
- X509証明書のサポート
- データ暗号化メカニズム
- ストリーム暗号
- OpenSSLサポート
データベース
- さまざまなデータベース(SQLite、MySQL、ODBCなど)との相互作用
Data::SQLite::Connector::registerConnector(); Data::Session ses("SQLite", "mydb.db"); int count = 0; ses << "SELECT COUNT(*) FROM PERSON", into(count), now; cout << "People in DB " << count; string firstName(""; string lastName(""); int age = 0; ses << "INSERT INTO PERSON VALUES (:fn, :ln, :age)", use(firstName), use(lastName), use(age), now; ses << "SELECT (firstname, lastname, age) FROM Person", into(firstName), into(lastName), into(age, -1), now; Data::SQLite::Connector::unregisterConnector();
- セッションプール
- レコードセット
Statement select(session); select << "SELECT * FROM Person"; select.execute(); RecordSet rs(select);
- タプル
struct Person { string fullname, city; size_t age; }; … typedef Tuple<string, string, int> Person; vector<Person> people; people.push_back(Person("Bart Simpson", "Springfield", 12)); people.push_back(Person("Lisa Simpson", "Springfield", 10)); Statement insert(session); insert << "INSERT INTO Person VALUES(:name, :address, :age)", use(people), now;
ファイルシステム
- ファイルとディレクトリのプラットフォームに依存しない作業
Path p_wind("C:\\Windows\\system32\\cmd.exe"); Path p_unix("/bin/sh"); p_wind = "projects\\poco"; p_unix = "projects/poco"; p_unix.parse("/usr/include/stdio.h", Path::PATH_UNIX); bool ok = p_unix.tryParse("/usr/*/stdio.h"); ok = p_unix.tryParse("/usr/include/stdio.h", Path::PATH_UNIX); ok = p_unix.tryParse("/usr/include/stdio.h", Path::PATH_WINDOWS); ok = p_unix.tryParse("DSK$PROJ:[POCO]BUILD.COM", Path::PATH_GUESS);
ログを操作する
- 強力なログ管理ツール
- ログのフォーマット
- ログ転送チャネル
// AutoPtr<SimpleFileChannel> pChannel(new SimpleFileChannel); pChannel->setProperty("path", "log.log"); pChannel->setProperty("rotation", "2 K"); Logger::root().setChannel(pChannel); Logger& logger = Logger::get("TestLogger"); // TestLogger for (int i = 0; i < 13; ++i) logger.information(" 13 "); // AutoPtr<FileChannel> pChannel(new FileChannel); pChannel->setProperty("path", " log.log"); pChannel->setProperty("rotation", "2 K"); pChannel->setProperty("archive", "timestamp"); Logger::root().setChannel(pChannel); Logger& logger = Logger::get("TestLogger"); // TestLogger for (int i = 0; i < 13; ++i) logger.information(" 13 "); // AutoPtr<ConsoleChannel> pCons(new ConsoleChannel); AutoPtr<AsyncChannel> pAsync(new AsyncChannel(pCons)); Logger::root().setChannel(pAsync); Logger& logger = Logger::get("TestLogger"); // TestLogger for (int i = 0; i < 13; ++i) logger.information(" 13 "); //- AutoPtr<ConsoleChannel> pCons(new ConsoleChannel); AutoPtr<SimpleFileChannel> pFile(new SimpleFileChannel("test.log")); AutoPtr<SplitterChannel> pSplitter(new SplitterChannel); pSplitter->addChannel(pCons); pSplitter->addChannel(pFile); Logger::root().setChannel(pSplitter); Logger::root().information(" "); Logger& logger = Logger::get("TestLogger"); LogStream lstr(logger); lstr << " " << endl; // AutoPtr<ConsoleChannel> pCons(new ConsoleChannel); AutoPtr<PatternFormatter> pPF(new PatternFormatter); // "-- :: : " pPF->setProperty("pattern", "%Y-%m-%d %H:%M:%S %s: %t"); AutoPtr<FormattingChannel> pFC(new FormattingChannel(pPF, pCons)); Logger::root().setChannel(pFC); Logger::get("TestChannel").information(" ");
マルチスレッド
- プラットフォームに依存しないスレッドおよびスレッドプールのサポート
// Runnable. Hello JAVA. class ThreadRunner: public Runnable { virtual void run() { cout << " " << endl; } }; // class ThreadRunnerNoRunnable { void norun() { cout << " " << endl; } }; … ThreadRunner runnable; Thread thread; thread.start(runnable); // thread.join(); // ThreadRunnerNoRunnable norunnable; RunnableAdapter< ThreadRunnerNoRunnable > runnable2(norunnable, & ThreadRunnerNoRunnable::norun); Thread thread2; Thread2.start(norunnable); // Thread2.join(); // // class ThreadRunner: public Runnable { virtual void run() { static int num; cout << " " << endl; for (int i=0; i<100; ++i) ++num; } }; … ThreadRunner runnable1, runnable2, runnable3; // ThreadPool::defaultPool().start(runnable1); ThreadPool::defaultPool().start(runnable2); ThreadPool::defaultPool().start(runnable3); // ThreadPool::defaultPool().joinAll();
- ストリーム同期ツール
class ThreadRunner: public Runnable { public: ThreadRunner(int &num, Mutex& mutex) : num(num), mutex(mutex) {} virtual void run() { while (num < 100) { ScopedLock<Mutex> lock(mutex); // , for (int i=0; i<5; ++i) cout << "TID:" << Thread::currentTid() << " NUM:" << ++num << endl; Thread::sleep(100); } } private: int& num; Mutex& mutex; }; ... int num = 0; Mutex mutex; Thread th1; ThreadRunner tr1(num,mutex); th1.start(tr1); while (num < 100) { ScopedLock<Mutex> lock(mutex); // , for (int i=0; i<5; ++i) cout << "TID:" << Thread::currentTid() << " NUM:" << ++num << endl; Thread::sleep(100); } th1.join();
- 作業キュー
- タイマー
- タスクマネージャー
- アクティブオブジェクト:アクティビティとアクティブメソッド
ネットワーク技術
- ソケット
Net::SocketAddress sa("www.habrahabr.ru", 80); Net::StreamSocket socket(sa); Net::SocketStream str(socket); str << "GET / HTTP/1.1\r\n" "Host: habrahabr.ru\r\n" "\r\n"; str.flush(); StreamCopier::copyStream(str, cout); // Net::ServerSocket srv(8080); // while(true) { Net::StreamSocket ss = srv.acceptConnection(); { Net::SocketStream str(ss); str << "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "\r\n" "<html><head><title> </title></head>" "<body><h1><a href=\"http://habrahabr.ru\"> .</a></h1></body></html>" << flush; } }
- マルチスレッドサーバー
- DNS
const HostEntry& entry = DNS::hostByName("www.habrahabr.ru"); cout << " : " << entry.name() << endl; const HostEntry::AliasList& aliases = entry.aliases(); for (HostEntry::AliasList::const_iterator it1 = aliases.begin(); it1 != aliases.end(); ++it1) cout << ": " << *it1 << endl; const HostEntry::AddressList& addrs = entry.addresses(); for (HostEntry::AddressList::const_iterator it2 = addrs.begin(); it2 != addrs.end(); ++it2) cout << "IP: " << it2->toString() << endl;
- 一部のアプリケーション層プロトコル(FTP、SMTPなど)のクライアント
- HTTP(S)サーバー、HTTP認証
- C ++コードのコンパイラ-HTML挿入、HTMLフォーム処理、MIME
- URIサポート、UUID
- RFC 6455サポート
- SSL / TLSサポート
プロセス
- プロセスの操作(開始、停止)
cout << " PID: " << Process::id() << endl; vector<string> args; args.push_back("shell32"); args.push_back("ShellAboutA"); Process::launch("rundll32", args);
- プロセス同期
- 共有メモリメカニズム
File file("Shared.dat"); SharedMemory mem(file, SharedMemory::AM_READ); cout << &*mem.begin() << endl;
ストリーミング操作
- BASE-64、HexBinaryのストリームコーディング/デコーディング
Base64Encoder encoder(cout); encoder << " Base64 stdout";
- メモリ入出力ストリーム
- URIストリームのサポート
Net::HTTPStreamFactory::registerFactory(); auto_ptr<istream> input( URIStreamOpener::defaultOpener().open("http://habrahabr.ru") ); cout << input->rdbuf();
テキストエンコーディング
- UTF-8およびUnicodeとの間のエンコードをサポート
string utf8(" UTF-8 ."); UTF8Encoding decoder; TextIterator end(utf8); for (TextIterator iter(utf8, decoder); iter != end; ++iter) int unicode = *iter;
- エンコード変換をサポート
string latin(" Latin1 ."); Latin1Encoding decoder; UTF8Encoding encoder; OutputStreamConverter converter(cout, decoder, encoder); converter << latin << endl; // latin - UTF-8
実用性
- コンソールおよびサーバーアプリケーションを作成するためのフレームワーク。
- コマンドライン引数のサポート
構成
- UnixデーモンとWindowsサービスの作成
XML
- DOM、SAX2をサポート
- 読み取りモードと書き込みモードの両方をサポート
おわりに
結論として、これらのモジュールには特別な注意が必要であり、別の記事が必要なため、いくつかのモジュールの説明は省略されています。 この図書館には明るい未来があると心から信じています。 また、POCOの新しいC ++ 11標準の利点もいくつか見たいと思います。
次の記事では、POCOの特定の事項について説明します。 客観的なコメントや異議を申し上げます。
読んでくれてありがとう。