nlib
nlibメインページ

Windows, Linux, FreeBSD, OS X, Cygwin及び任天堂の開発環境に対応したライブラリの集合です。

nlibについて

nlibはWindows, Linux, FreeBSD, OS X, Cygwin及び任天堂の開発環境に対して同一のI/Fを利用したプログラミングが可能な、ユーザーランド上で動作するライブラリ群を提供することを目的として開発されています。 開発はsoftware centricに行われ、適切で現実的なコーディングルール(nlibのコーディングルール)と個別の開発環境からの独立性が確保されたI/Fと実装によって、複数の開発環境に対して同時並行的に高い品質と性能及び信頼性を維持しつつ行われることにフォーカスしています。

nlibが実装している機能

主に以下のような機能が実装されています。
  • XML及びJSONの読み書き
  • 高効率なメモリアロケータ
  • googletest互換のテストフレームワーク
  • SSE4.2/NEON両対応のコード開発を可能とするラッパーライブラリ。4x4行列及び3次元,4次元ベクトルに対する各種計算のサポートを含みます。
  • キーワード検索等のための簡潔データ構造ライブラリ
  • UTF-8の読み書きや正規化, UTF-16/UTF-32との変換
  • スレッド, ミューテックス, 条件変数, TLS, バリア, リードライトロック, アトミック変数, 等
  • システムメモリの取得と解放, 時刻の取得, ファイルの読み書き, 等
  • 基本的なロックフリーデータ構造とアルゴリズム
  • その他、多数のプラットフォームや複数のコンパイラに対応するための基底となるCリンケージの関数群やマクロ定義

nlibが動作する環境

nlibは現在以下の環境でコンパイル及び動作確認が行われています。
Platform Library types Remarks
Windows Visual Studio 2015 64bit static library, DLL Update 3
32bit static library
Visual Studio 2013 64bit static library, DLL Update 5, Express Edition is available
32bit static library
Visual Studio 2012 64bit static library, DLL Update 5, Express Edition is available
32bit static library
Cygwin 64bit static library gcc 5.4.0, newlib, libstdc++
Bash on Ubuntu on Windows 64bit shared library gcc 4.8.4, clang 3.4, glibc, libstdc++
Linux Ubuntu 16.04 LTS 64bit shared library gcc 5.3.1, clang 3.8, glibc, libstdc++, https://atlas.hashicorp.com/ubuntu/
Ubuntu 14.04 LTS 64bit gcc 4.8.4, clang 3.4, glibc, libstdc++, https://atlas.hashicorp.com/ubuntu/
32bit
CentOS 7 (v1608.01) 64bit gcc 4.8.5, glibc, libstdc++, https://atlas.hashicorp.com/centos/
Fedora 24 64bit gcc 6.1.1, clang 3.8, glibc, libstdc++. https://atlas.hashicorp.com/fedora/
Alpine 3.4.0 64bit gcc 5.3.0, musl libc, libstdc++, https://atlas.hashicorp.com/maier
FreeBSD FreeBSD 11.0 64bit shared library clang 3.8, BSD libc, libc++, https://atlas.hashicorp.com/freebsd
OS X OS X 10.11 (El Capitan) 64bit shared library Xcode 8.0
CTR CTR-SDK 11.5 32bit static library CTR_SDK-11_5_1-20160622-ja.zip
armcc_4_1_nintendo-b1454-20150227.zip
Cafe CafeSDK 2.13.01 32bit static library cafe_sdk-2_13_01-20150728.zip
MULTI-5_3_26-20150918.zip
コンパイラのバージョン等により、適宜C++11の機能を利用してコンパイルされるようになっています(nlibで利用しているC++11の機能)。

nlibのサポート方針等

サポート方法については、パッケージのリリース元にお問い合わせください。 FAQ 等も併せてお読みください。 なお、今後の開発予定やリリース予定日のドキュメント等は作成や公開されずに、現在の実装について本ドキュメント及びサンプルで説明される形となります。 サポート及びバグフィックスはその時点での最新バージョンに対して行われます。 特定のプロジェクトに対してのみの特別バージョン等の提供や特別扱いのサポートが行われることはありません。 これらは開発チームの規模を最小限に抑えるために必要なルールとなっています。
また、やむを得ず互換性が失われるような変更が予告なしに行われる場合もあります。 ご了承ください。
利用の際には利用する機能について受け入れテスト等で、期待通りの動作をするか、速度は十分にでるか、メモリ消費量等は許容範囲内かを事前に確認しておくのがよいでしょう。 受け入れテストを作成しておくことは、nlibのアップデートによるトラブルを回避するためにも役に立ちます。 そのような受け入れテストの作成にtestingライブラリを利用するのはよい考えです。
バグ報告は可能であれば、再現コードをnn::nlib::testing形式のテストコードとして記述してそれを報告に含めると迅速に修正されるかもしれません。

nlibのパッケージに関する説明

パッケージによって収録されているライブラリや対応プラットフォームが異なりますのでご注意ください。

ディレクトリ構成

以下のような構成になっています。
    ├── bin
    │   └── cmake                 # Command-line tools
    ├── cmake                      # Common Cmake scripts
    ├── documents-ja(documents-en)
    │   └── API                   # Reference Manual
    │       ├── html              # HTML version of the Reference Manual
    │       └── searchdata.xml    # Search index
    ├── include                    # Include files (in `system/include` for Cafe)
    │   ├── nn
    │   │   └── nlib
    │   │       ├── exi
    │   │       ├── heap
    │   │       ├── msgpack
    │   │       │   └── jsonrpc
    │   │       ├── oss
    │   │       ├── simd
    │   │       ├── succinct
    │   │       ├── testing
    │   │       ├── threading
    │   │       └── unicode
    │   ├── lz4.h
    │   ├── lz4hc.h
    │   ├── lz4frame.h
    │   ├── sqlite3.h
    │   └── sqlite3ext.h
    ├── lib                        # Platform-specific library files (`system/lib` for Cafe, `libraries` for CTR)
    ├── samples                    # Source code for samples
    │  ├── cmake
    │  └── sources
    │      ├── exi
    │      ├── heap
    │      ├── misc
    │      ├── msgpack
    │      ├── oss
    │      ├── succinct
    │      └── testing
    └── setup
        ├── nlib.natvis
        ├── setup-bash-ubuntu-windows-tools.sh
        ├── setup-cygwin-tools.sh
        ├── setup-msvc-libraries.sh
        └── setup-vagrant-plugins.sh

個別プラットフォームに関する説明事項

各種ライブラリの説明

libnライブラリ(libn.a, libn.so, n-vc120amd64.lib, n-vc120dllamd64.dll等)
このライブラリではプラットフォーム間の差異を吸収しているCリンケージを持つ関数群で構成されます。
具体的には以下のような関数を含みます。
miscライブラリ(libnx_misc.a, libnx_misc.so, nx_misc-vc120amd64.lib, nx_misc-vc120dllamd64.dll等)
このライブラリは、比較的小規模なクラスで構成されたクラスライブラリです。 多くのプログラムで使うであろう機能が実装されています。
具体的には以下のものを含みます。
  • InputStream, OutputStreamを基底とする各種ストリームを扱うためのクラス群
  • UTF-8文字列をストリームからvalidationしつつ読み書きするためのクラス(TextReader, TextWriter)
  • バイナリデータをストリームから読み書きするためのクラス(BinaryReader, BinaryWriter)
  • ユニコードを扱うためのクラス
  • スレッドを扱うためのクラスや関数群
  • 日時や時間情報を扱うためのクラスや関数群
    • 日時を加減算したり、日付文字列(RFC2822, W3CDTF)をパースしたり作成するクラス(DateTime, TimeSpan)
  • URIを扱うためのクラスや関数群
    • URIパーサー(Uri)
    • URI Template(RFC6570) を処理するためのクラス(UriTemplate)
    • 環境ごとに異なる文字列となることの多いファイルパスをURI文字列に標準化するためのクラス(NativePathMapper)
  • 非同期ファイルアクセスを行うためのクラス(threading::AsyncFileIo)
  • 基本的なロックフリーデータ構造とアルゴリズム
  • 各種ガシェットクラス
    • std::unique_ptr代替クラス(UniquePtr)。C++11ではstd::unique_ptrtypedefされる。
    • シングルトンクラス(Singleton, SimpleSingleton)
    • 拡張時にメモリの解放(と要素のコピー)が必要とならないstd::vector類似クラス(Nlist)
    • コマンドライン文字列を解析するためのクラス(Nflags)
    • ハンドル作成支援クラス(HandleMaker)
名前空間はnn::nlib, nn::nlib::unicode, nn::nlib::threadingです。
exiライブラリ(libnx_exi.a, libnx_exi.so, nx_exi-vc120amd64.lib, nx_exi-vc120dllamd64.dll等)
バイナリXMLを読み書きするライブラリです。テキストのXMLを読み書きすることも可能です。 XML名前空間をサポートしていて、プログラミングの簡単なPull parsing APIを備えています。
名前空間はnn::nlib::exiです。
heapライブラリ(libnx_heap.a, libnx_heap.so, nx_heap.lib, nx_heap-vc120dllamd64.dll等)
マルチスレッドでのメモリの確保と解放に関して最適化されたヒープライブラリで、nmalloc()/nfree()(とそれらを実装するheap::CachedHeap, heap::CentralHeap)は、多段のフリーリストを利用することでフラグメンテーションの抑制を行い、性能の劣化を抑えています。 また、小さいサイズのメモリの場合は各スレッド毎にキャッシュを保持することにより、ロックをかけずにメモリの割り当てと解放が可能になっていてマルチスレッドでの性能劣化を抑制しています。 フリーリスト内のポインタはマングルされているか割り当て状態がチェックされていて、外部からのメモリの書き換えによる不正利用が行いにくいように実装されています。
名前空間はnn::nlib::heap及びグローバル名前空間(Cリンケージの関数)です。
succinctライブラリ(libnx_succinct.a, libnx_succinct.so, nx_succinct-vc120amd64.lib, nx_succinct-vc120dllamd64.dll等)
簡潔データ構造を扱うためのライブラリです。 簡潔データ構造とは、圧縮したままの状態で中身の検索を行うことができるデータ構造とお考えください。
succinctライブラリは以下のものを含みます。
  • 各種簡潔ベクトルクラスの実装
  • 括弧列(Balanced Parentheses)を実装したクラス
  • LOUDS(Level-Order Unary Degree Sequence)を実装したクラス
  • Trieの実装
  • Aho Corasick法のための高圧縮なインデックスを作成し、文字列の検索に利用するためのクラス
名前空間はnn::nlib::succinctです。
msgpackライブラリ(libnx_msgpack.a, libnx_msgpack.so, nx_msgpack-vc120amd64.lib, nx_msgpack-vc120dllamd64.dll等)
MessagePackとJSONを読み書きするためのライブラリです。 CSVをパースするクラスも含まれています。
msgpackライブラリは以下のものを含みます。
  • ストリームからJSONを読み書きするためのクラス
  • ストリームからmsgpackを読み書きするためのクラス
  • メモリ上のmsgpackを高速に解釈するためのクラス
  • CSVを読み込むためのクラス
  • 読み込んだJSONやmsgpack、及びCSVのデータを保持するためのクラス
  • JSON-RPCのための実装
名前空間はnn::nlib::msgpackです。
testingライブラリ(libnx_testing.a, libnx_testing.so, nx_testing-vc120amd64.lib, nx_testing-vc120dllamd64.dll等)
移植性の高いテストコードを記述するためのライブラリです。 googletestで書かれたテストとある程度のソースコード互換性を持つテストフレームワークです。
名前空間はnn::nlib::testing(googletestとの互換性のためtesting名前空間にエイリアスされている)です。miscライブラリに依存します。
ossライブラリ(libnx_oss_bsdiff.a, libnx_oss_sqlite3.a, libnx_oss_lz4.a等)
オープンソース・ソフトウェア(OSS)のコード、及びOSSから派生したコード、及びOSSにアクセスするためのコードが格納されます。 利用する場合にはOSSライセンスの処理が必要となります。
現在は、以下のライブラリが含まれています。それぞれが別々のライブラリファイルとしてビルドされています。
  • bsdiffbzlib2ではなくzlibを使うように改変してライブラリ化したもの、及びそのコマンドラインプログラム
  • SQLite3nlibが提供しているI/Fを利用して動作するように改変したもの、及びそのコマンドラインシェル
  • LZ4zlibに比べて圧縮では約20倍、展開では約5倍の速度で動作するアルゴリズムです。
名前空間はnn::nlib::oss及びグローバル名前空間(Cリンケージの関数)です。
simdライブラリ(大半がインライン関数でmiscライブラリに含まれる)
SIMD命令を用いることにより、プログラムを大幅に高速化することが可能です。 simdライブラリは、SSE4.2とNEONに両対応したコードを記述するためのライブラリです。
各種整数と単精度浮動小数点数の計算に対応していて、高速な演算を行うコードを記述可能です。
なお、単精度浮動小数点数の計算については、SSEやNEONに対応していない環境でも利用することが可能です。
CAFEにおいてはpaired singleを利用するように最適化されています。
つまり、同一のコードを書くことで、下記の環境に対応することができます。
  • x86系プロセッサではSSE4.2を利用した高速化が適用されたコードにコンパイルされます。
  • NEONをサポートするプロセッサではNEONを利用した高速化が適用されたコードにコンパイルされます。
  • CAFEではpaired singleを利用した高速化が適用されたコードにコンパイルされます(浮動小数点演算のみ, 4次元ベクトル等を値返しするI/FのためCAFE-SDKの行列計算等よりかなり遅い)。
  • CTRではgenericなコードがコンパイルされます(浮動小数点演算のみ)。
名前空間はnn::nlib::simdです。

nlibのライブラリ間の依存関係

nlibの各ライブラリ間の依存関係は下図のようになります。

dot_inline_dotgraph_32.png

nlibで利用しているC++11の機能

nlibではコンパイラの種類やバージョンによって、C++11の機能を利用してコンパイルされています。 以下にC++11の機能とnlibで利用できる互換用マクロ等、及びC++11を利用してコンパイルされる コンパイラについて表にまとめておきます。 なお、clangについてはバージョンではなく__has_feature()マクロ及び__has_include()マクロによって判定されます。
その他の環境ではC++11の機能は利用されません。
C++11の機能 識別用マクロ C++03互換用マクロやtypedef等 Visual Studio gcc
Rvalue references NLIB_CXX11_RVALUE_REFERENCES なし 2010 4.3
Variadic templates NLIB_CXX11_VARIADIC_TEMPLATES なし 2013 4.7
Static assertions NLIB_CXX11_STATIC_ASSERTIONS NLIB_STATIC_ASSERT() 2010 4.3
Null pointer constant NLIB_CXX11_NULL_POINTER_CONSTANT nn::nlib::nullptr, nn::nlib::nullptr_t 2010 4.6
Deleted functions NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS NLIB_DISALLOW_COPY_AND_ASSIGN() 2015 4.4
Explicit conversion operators NLIB_CXX11_EXPLICIT_CONVERSION_OPERATORS NLIB_SAFE_BOOL() 2013 4.6
Alias templates NLIB_CXX11_TEMPLATE_ALIAS なし 2013 4.7
constexpr NLIB_CXX11_CONSTEXPR NLIB_CEXPR 2015 4.7
char16_t, char32_t NLIB_CXX11_NEW_CHARACTER_TYPES nlib_utf16_t, nlib_utf32_t 2015 4.4
alignas NLIB_CXX11_ALIGNMENT_SUPPORT NLIB_ALIGNAS() 2015 4.8
Explicit virtual overrides NLIB_CXX11_EXPLICIT_VIRTUAL_OVERRIDES NLIB_OVERRIDE 2012 4.7
final NLIB_CXX11_EXPLICIT_VIRTUAL_OVERRIDES NLIB_FINAL 2012 4.7
noexcept NLIB_CXX11_NOEXCEPT NLIB_NOEXCEPT 2015 4.6
Range-based for NLIB_CXX11_RANGE_BASED_FOR なし 2012 4.6
lambda NLIB_CXX11_LAMBDAS なし 2012 4.7
Delegating constructors NLIB_CXX11_DELEGATING_CONSTRUCTORS なし 2013 4.7
std::unique_ptr NLIB_CXX11_UNIQUEPTR nn::nlib::UniquePtr 2013 4.7
#include <random> NLIB_CXX11_STDLIB_RANDOM なし 2013 4.8
#include <chrono> NLIB_CXX11_STDLIB_CHRONO nn::nlib::DateTime との変換 2012 4.7
#include <atomic> NLIB_CXX11_STDLIB_ATOMIC NLIB_MEMORY_ORDER_SEQ_CST2012 4.8
#include <array> NLIB_CXX11_STDLIB_ARRAY なし 2012 4.5
#include <unordered_map>
#include <unordered_set>
NLIB_CXX11_STDLIB_UNORDERED なし 2012 4.5
#include <tuple> NLIB_CXX11_STDLIB_TUPLE なし 2012 4.5

nlibのコーディングルール

nlibの基本的なコーディングルール

nlibのコーディングルールは、(最新の)Google C++ Style Guide(若干古いが日本語訳)に若干の変更と緩和を行ったものになっています。
Google C++ Style Guideを利用する理由については以下の点を挙げることが可能です。
  • コーディングルールの文書にアクセスしやすい。公式ではないにしろ翻訳もされている。
  • ゲーム業界での一般的なコーディングルールと同様にC++例外とRTTIの利用を禁止している。
  • 今までに継続的に更新されている。
  • 更新毎のコーディングルールの変化は穏当なもので、突然全く変わってしまう、といったことがなかった。
  • 5年後においてもメンテナンスされていることが期待できる。
変更点及び緩和点は以下のとおりです。
コーディングルール Google C++ Style Guide nlib
行の長さ 80 100
インデント 2 4
パラメータの順序 入力が先で出力が後 出力が先で入力が後
デフォルト引数 原則として禁止 以下の場合以外では利用可能。
  • コンストラクタ。デフォルト値により引数が1つになるまで省略可能な場合に問題を引き起こすため。
  • 仮想関数。オーバーライドした関数でデフォルト引数が違う場合に問題を引き起こすため。
  • 関数ポインタとして利用されうる場合。コーディングに混乱を引き起こすため。
ファイル名 file_name.cc FileName.cpp(サンプルではfile_name.cpp)
インクルードガード 更に#pragma onceをつける(Visual Studioでのコンパイル高速化のため)
Boostの利用 ライブラリ本体では利用しない(テスト等では自由)
アクセサ関数名 get_xyz() / set_xyz() GetXyz() / SetXyz()
参照型の引数 非const参照は禁止 nlibでは以下については例外的に非const参照を利用可能にしている
  • std::swap()の特殊化を行う場合
  • C++03でmove semanticsを真似するコード
  • 機能が単純なクラス。例えばScopedLockクラスのようにロックを保持するだけの機能を持っているクラス。
  • nn::nlib::UniquePtrを引数で渡す場合(値渡しは非効率だし、UniquePtrへのポインタを渡すというのも変である)
C++11の利用 ヘッダ、及びソースコードはC++03のコンパイラでもコンパイルできるようにしておくこと。
  • C++11を使うなということではない。ムーブコンストラクタ, range based for, Explicit virtual overrides, Explicit conversion operators 等は積極的にサポートするべきである。
  • 可能ならばマクロ等を利用して同一のソースコードがコンパイルされるようにすること。不可能な場合でも、C++03から利用できる同等の機能を実装しておくこと。
nullptr C++11なら利用 C++03が使われているうちは、原則としてnullptr_tnullptrを使わないこと
  • C++03でnullptrを実現するためのnullptrイディオムは、複数のライブラリで定義されている場合にエラーとなるので、グローバル名前空間で定義できない
  • nlibでは、C++03の場合は nn::nlib::nullptr_t, nn::nlib::nullptrとして定義されている
  • 紛らわしいオーバーロードを使わないことで、nullptrが必要となる状況の殆どは回避できるはずである
constexpr C++11なら利用 当分の間、constexprの利用は自明なケース以外では見合わせること
  • 残念ながら、constexprを積極的に利用したコードは、コンパイラ毎の挙動の違いによりコンパイルエラーを多発させる要因になるという移植性におけるデメリットが存在する。
  • 自明なケースとは、空の定数オブジェクト, 定数を設定するだけの単純なコンストラクタ等のconstexprをサポートするどのコンパイラでもコンパイルが通ることを期待できる場合のことである。
コメント
  • 翻訳の手間を考慮すると、公開ヘッダには非ASCII文字(非英語)のコメントを書くべきではない(翻訳される可能性が全くない場合は考慮の必要はない)。
  • 詳細なコメントを書きたい場合は、ソースコードファイルか、リファレンス・マニュアルに記述すること。
  • doxygenコメントを公開ヘッダに書いてはいけない。ドキュメントの変更による再コンパイルという問題があるし、翻訳の手間を増大させる。 ライブラリ毎にmanual_ja.hmanual_en.hといったファイルを用意してそこに記述すべきである。
  • リファレンス・マニュアル内の改行は文単位で行い、文の途中で改行してはならない。これは、翻訳支援ソフトの都合によるものである。 このことは、前述の1行100桁制限よりも優先される必要がある。

コーディングスタイルのチェックと矯正

コーディングスタイルは、cpplintを用いて簡単にチェックすることができます。
警告基準は以下のように若干緩和されています。
  • --linelength=100 を指定して、1行は100行以内であるとしている。
  • cpplintのlegal/copyright, build/include_alpha, whitespace/newlineによる警告は抑制されている。
  • std::swap()の利用に際してヘッダalgorithmのインクルードは要求されないよう緩和している。
Makefileに以下のようなルールを書いておけば、手軽にチェックをかけることができます。
cpplint:
-./cpplint.py --linelength=100 \
$(shell find ./include/ -path "*.h") \
$(shell find ./sources/ -path "*.cpp" -or -path "*.h") 2>&1 | tee cpplint.log
また、nlibclang-checkによるソースコードの検査にも対応しています。 cmakeでMakefileを生成すると、compile_commands.jsonというファイルが一緒に作成され、clang-checkはこれを利用して動作します。
詳しくは、clangマニュアルのJSON Compilation Database Format Specification を御覧ください。

コーディングスタイルの自動整形

clang-formatを用いるとインデント等を好みの方法に統一することが可能です。 nlibで用いている設定が .clang-formatファイル(clang3.5用です)としてnlibのパッケージに含まれていて利用することが可能です。 まず、clang-formatで一括してソースコードの大まかな変換を行い、cpplint.pyでより細かい日常的なチェックを行うことをおすすめします。

コンパイル時の警告の設定等

複数のコンパイラや実行環境でテストすることにより、コードの品質を向上させることが可能です。 各コンパイラで比較的厳しめのワーニングレベルを設定します。
  • Visual Studio 2012 以降の全てのバージョンでコンパイルを成功させること。/W4 オプションを利用した上で原則として警告を無くすこと。
    • pragmaによる警告の抑制は容認される。
    • 常に最新のUpdateを適用し、コードで_MSC_FULL_VERをチェックすること。
    • 定期的にVisual Studioのコード分析を利用して警告を減らしておくこと。
  • cygwin(32bit)及びUbuntuにおいてバイナリパッケージで手に入る最新版のgcc, clangでコンパイルを成功させること。-Wall -Wextraを利用した上で原則として警告を無くすこと。
    • cygwinは常に最新にしておくこと。 cygwinのアップデートでビルド動作がおかしくなった場合はビルドスクリプトの方を修正すること。
    • pragmaによる警告の抑制は容認される。
    • -Wstack-usage=65536 を利用し、スタックを使い過ぎないようにすること。
    • -fstack-protector を利用すること。
  • CAFEの開発環境で警告なしにコンパイルを成功させること。
  • CTRの開発環境でコンパイルを成功させること。
  • 各種64bit環境でも同様にコンパイルが成功することが望ましい。
  • doxygenの警告もなくしておくこと。
cpplint.pyの警告をゼロにし、各種環境でのコンパイルとテストを通すことがnlibの基本的なリリース基準になっています。

追加のルールや慣習

  • 原則として、Platform.hで定義される関数の宣言や実装以外のコードは利用する可能性のある全環境でコンパイルできるコードで記述されている必要がある。ただしSIMD命令等によって機種別に最適化されたコードが含まれることは容認される。
  • NLIB_FINAL, NLIB_OVERRIDE等のマクロやtypedefを利用してC++11の機能を安全に導入し、C++11やC++14以降への連続的な移行を可能にすること。
  • エラー値は可能であればPOSIX.1 2008のエラーコードを利用し、エラー値の型はerrno_tとすること(https://www.jpcert.or.jp/sc-rules/c-dcl09-c.html)。
    これは、
    typedef int errno_t;
    とされていて、エラー値であることが分かりやすくなっている。
    • POSIX.1 2008のエラーコードの値は十分に小さい整数値なので、ARMのようなプロセッサで効率的に即値ロードできる。
  • 例外・RTTIを利用せずに実装しなくてはならないが、nlibを利用する側のコードがこれらを利用する場合を想定したコードを記述すること(例外安全性等)。
  • malloc(), free()等はnlib_malloc(), nlib_free()等を利用すること。
  • newは、new (std::nothrow)を利用すること。
  • ライブラリ内部でグローバルのnewをオーバーロードしてはならない。
    • このオーバーロードは依存関係のないはずの他のライブラリの挙動に影響を与えてしまうのでやってはならない。
  • マルチバイト文字列はASCII文字列かUTF-8文字列のどちらかにすること。
    • WindowsにおいてもUTF-8で渡す実装でなくてはならない。パス文字列やnlib_printf()に渡す文字列はnlib内部でUTF-16に変換された上でWin32 APIに渡されている。
    • コマンドライン引数処理(Nflags)は例外
  • char型が符号付きでも符号無しでも正常に動作するようにしておくこと。
    • signed charを用いれば明示的に符号付きの値として扱うことができる。
  • wchar_tに関してはwchar_tが16bitの場合はUTF-16として、32bitの場合はUTF-32としてサポートすること。
    • NLIB_WCHAR_SIZEが2か4のいずれかに定義されるのでそれで判断することができる。
  • UTF-16文字の型には nlib_utf16_t, UTF-32文字の型には nlib_utf32_tを利用すること。
    • これらはC++11の場合はそれぞれ、char16_t, char32_ttypedefとなる。
  • 原則としてUTF-16やUTF-32より、UTF-8を優先すること。
    • UTF-8の方がメモリ消費量が少なく、複数プラットフォームへの対応が容易である。
    • サロゲートペアや結合文字の存在により、UTF-16やUTF-32を利用しても必ずしも1文字を固定長で表現することができない。
    • nlib_strcplen_ex()を使うことにより、validationを行いつつコードポイント数とバイト長を同時に求めることができる。更にSIMDがサポートされている場合にはこの動作をより高速に行うことができる。
  • ムーブコンストラクタ、ムーブ代入演算子を定義する場合には、NLIB_CXX11_RVALUE_REFERENCESで切り分けられたコード内での定義の他に、C++03でも同等の機能を実現できるよう、以下のようなメンバ関数を定義しなければならない。
    Type::Type(Type& rhs, ::nn::nlib::move_tag); // ムーブコンストラクタと同じ動作をさせる。
    Type& Type::assign(Type& rhs, ::nn::nlib::move_tag); // ムーブ代入演算子と同じ動作をさせる。
    boost::moveのような素晴らしい手法も存在するが、結局完全な互換性は達成できないのでこの手法は利用しない。
  • type_traitsの利用は慎重に行うこと。C++11のこの機能はコンパイラやそのバージョンによってバグがあったり実装が抜けていたり、といったことがある。 nn/nlib/TypeTraits.h に一応のラップが行われているが、やむを得ない場合にのみ利用すること。
  • Non-copyable Mixinを使わないこと。
    • 代わりに、NLIB_DISALLOW_COPY_AND_ASSIGN()を使うこと。
    • 継承階層を増やすことが、ソースコードの解析プログラムやドキュメンテーションシステムに悪影響を与えることがある。
  • C標準ライブラリのヘッダは .h形式のものをインクルードすること。理由は以下の2つ。
    • C++標準ライブラリのヘッダが壊れているような状況に対応するため
    • nn/nlib/Platform.hはCコンパイラでコンパイル可能である必要があることから、xxx.h形式のヘッダをインクルードする必要があるため、nlib内部でxxx.h形式とcxxx形式の両方の形式でインクルードすることに起因するコード上の混乱を抑制するため。
  • テストをgoogletest形式で記述して、どのプラットフォームでも単体テストが実行されている状態にしておくこと。
    • 特定のプラットフォーム向けの実装のバグや、特定の環境でしか見つからないバグを見つけることが容易になる。
    • どのプラットフォームでも実行する共通のテストと、PCのみで実行するテストを分けておくとよい。
      • PCのようなパワーのある環境では、ストレスをかけるテストや総当りのテストが記述しやすい。
      • PC環境ではOSSをテストプログラムで利用することが容易で、便利なことがある。
      • Windows環境ではDirectX等をテストプログラムで使うことができ、便利なことがある。
      • googletestが動作しない環境では、 testingライブラリを利用することが可能である。
      • gccでコンパイルしている場合は、gcovrを使うことでテストのカバレッジを自動計測することができる。
  • リファレンス・マニュアルはdoxygen形式で記述すること。
    • doxygenは継続的に改良されていて、5年後においても改良されつつ存在していることが期待できるドキュメンテーションシステムであるから。
    • doxygenコメントは各インクルードディレクトリにmanual.hというファイルを配置して、そこに記述すること。英語版のマニュアルの場合はmanual_en.hである。こうすることで複数言語版を同じレポジトリで管理することができる。
  • 可能であればcmakeでビルドできるようにすること。
    • cmakeはWindowsとLinuxの両方で動作するようなC/C++のコードを記述する場合において代表的な選択肢となっている。

CMakeについての紹介

サンプルのビルドにはcmakeを利用することが可能です。 CMakeはかつてMySQL(MariaDB)のビルドに採用されていることで有名でした。 現在はC/C++で記述されていてWindowsとLinuxの両方に対応している各種ソフトウェアの標準的なビルドシステムとしての地位を確立しています。 多くのOSSにCMakeLists.txtというファイルが含まれていることに気づいた方も多いと思います。 cmakeを利用すると、このCMakefiles.txtというスクリプトファイルを記述することで、GNU makeのMakefileやVisual Studio及びXcodeのプロジェクト等を生成することが可能です。
cmakeを利用するメリットは以下のとおりです。
  • 多くのシステムとコンパイラをサポートしています。
    • Windows, Linux, MacOS X, FreeBSD, IRIX, AIX, Sun OS, HP-UXなどに対応しています。
    • Visual Studioの各バージョン, Eclipse CDT, Xcodeといった複数のIDEに対応しています。
    • Visual Studioに関してはExpress Editionも利用可能ですし、最新バージョンへの対応もRC版が出る頃には完了しています。
    • 比較的簡単な設定を行うことでクロスコンパイルに対応することが可能です。
  • ビルド用の一時ファイル等がソース・ファイルのある場所を汚しません。つまりOut-Of-Treeビルドが可能です。複数の環境向けのバイナリを1つのソースツリーからビルドしたい場合は必ず必要となる機能です。
  • cmakeから別個独立した複数のプロジェクトを生成して利用することができるので、並列ビルドが容易です。
  • 利用するライブラリやツールの場所を自動的に探してくれます。
  • 利用するライブラリのインクルードパスの設定やライブラリのリンクがクロスプラットフォーム化されていて、環境ごとにパスが違ったとしても統一した記述が可能です。
  • インストーラを作成することができます(CPack)
    • NSIS, deb, rpm, tgz, 他
  • テストの実行や管理が可能です(CTest)
nlibではcmakeを利用することで、Visual Studioの各バージョンに対応したソリューションファイル,Unix, Cygwin用のMakefile等を生成しプログラムをビルドすることが可能となります。
また、パッケージ内の ./cmake/toolchain-cafe.cmake, ./cmake/toolchain-ctr.cmakeファイルにクロスコンパイル用の各種設定がされていて、CAFE/CTR版のサンプルプログラムもcmakeを利用してMakefileを生成し、ビルドすることが可能です。 なお、nlibのCAFE版及びCTR版には標準のmake, omake用のスクリプトも用意されています。

cmakeを使う際の注意点

  • Visual Studioのプロジェクトを生成するためにはWindows版のcmakeをインストールする必要があります。
  • cygwinのMakefileを生成するためにはcygwin版のcmakeをインストールする必要があります。
  • cmakeではDebugビルド, Releaseビルド毎に別々のディレクトリにVisual StudioやXcodeのプロジェクトやMakefileを出力する必要があります。

FAQ

このセクションでは、nlibを利用する際によく遭遇する状況と対処法について説明します。
new/deleteのオーバーロード
nlibはメモリの確保にはnew (std::nothrow)を利用しています。 アプリケーション、又は他のライブラリでnew/deleteをオーバーロードする場合には、operator new(size_t, const std::nothrow_t&)もオーバーロードする必要があります。
詳しくはheap_replace_mallocサンプルを御覧ください。
malloc等の置き換え
nlibmalloc, freeを直接使うことはしていません。代わりにnlib_malloc(), nlib_free()等を利用します。 これらの関数はweak関数として定義されていてユーザーが定義することで置き換え可能です。
ユーザー定義のヒープを利用したい場合にはこれらの関数を置き換える必要があります。 必要なのは、以下の関数です。
void* nlib_malloc(size_t size);
void nlib_free(void* ptr);
void* nlib_calloc(size_t nmemb, size_t size);
void* nlib_realloc(void* ptr, size_t size);
void* nlib_memalign(size_t alignment, size_t size); // not defined if WIN32 or CTR
詳しくはheap_replace_mallocサンプルを御覧ください。
コンパイルオプションについて
パッケージのcmake/common.cmake.win32等のファイルにプラットフォーム毎のスイッチ等の定義が記述されています。 参考にしてください。
コンパイルすると"MACRO_XXXX not defined, compile may fail"と表示される
コンパイラへのコマンドライン引数でMACRO_XXXXを定義するようにしてください。
私達のプロジェクトで最新版を利用すべきかどうか教えてください。
それはnlibを利用するプロジェクトの判断に委ねられます。 受け入れテストを記述しておくことで、そういった判断をより容易にすることができます。 ただし、サポートの対象となるのは最新版のみです。ご了承ください。
私達のプロジェクトのために専用パッケージをリリースしてください。
プロジェクトのニーズはプロジェクトの数だけ存在します。例えば、以下のようなものがあります。
  • 私達にはライブラリXは必要ないので取り除いたものをリリースしてください。
  • 私達にはサンプルを取り除いたものをリリースしてください。
  • 私達はVisual Studio 2012(32bit)を使っているので、Visual Studio 2012用のソリューションを構築済みの状態にしてリリースしてください。
これらのニーズに柔軟に応えることを可能にするために、nlibを利用するプロジェクト側においてnlibのパッケージを再構成、再パッケージを行いプロジェクト内においてのみ再配布することが認められています。
nlib_printf()でShift JIS文字列が表示できません。
nlib_printf()の入力文字列はUTF-8である必要があります。
半年前のリリースにバグがあるので修正パッチをリリースしてください。
バグの修正は最新版に反映されます。次回以降のリリースを組み込んでください。
私達のライブラリやフレームワークのやり方に合わせて貰えませんか?
それが公開されていて、Windows/Linux/FreeBSD/OS X/Cafe/CTRの全てに対応しているものならば可能かもしれません。 ご連絡ください。

Changelogs

2016-09-20

  • FreeBSD 11.0での動作確認を開始しました。これに伴いFreeBSD 10.3での動作確認を終了しました。
  • ossライブラリに収録されているSQLiteをバージョン3.14.1にアップデートしました。
  • nlib_bitreverse32()nlib_bitreverse64()が実装されました。
  • nlib_fd_open()O_EXCL(NLIB_FD_O_EXCL)の指定が可能になりました。
  • 既にファイルが存在する場合にはnlib_fd_create()が失敗するように変更しました。
  • nlib_strcplen2()nlib_strcplen()にリネームされました。nlib_strcplen2()は暫くのあいだマクロとして提供された後に削除されます。
  • nlib_popcnt()nlib_popcnt32()にリネームされました。nlib_popcnt()は暫くのあいだマクロとして提供された後に削除されます。
  • nlib_clz()nlib_clz32()にリネームされました。nlib_clz()は暫くのあいだマクロとして提供された後に削除されます。
  • nlib_ctz()nlib_ctz32()にリネームされました。nlib_ctz()は暫くのあいだマクロとして提供された後に削除されます。
  • deprecatedとなっていたファイルや関数を削除しました。
  • その他細かい変更と修正

2016-08-23

  • Bash on Ubuntu on Windowsでの動作確認を開始しました。コンパイル済みのライブラリはPC版のパッケージに含まれます。
  • heap::CentralHeap::FreeWithSize(), heap::CentralHeap::GetAllocSize(), heap::CentralHeap::Realloc()が追加されました。
  • nmalloc_query()のクエリにNMALLOC_QUERY_SET_COLOR, NMALLOC_QUERY_GET_COLOR, NMALLOC_QUERY_SET_NAME, NMALLOC_QUERY_GET_NAMEを追加しました。割り当てられた4096バイト以上の任意の領域に対して24bit整数値や文字列を関連付ける機能です。 利用方法はheapライブラリのobject_trackingサンプルを参考にしてください。
  • NMallocDumpModeNMALLOC_DUMP_PAGESUMMARYを追加しました。
  • TLSインデックスの割当に失敗した場合のnmalloc等の動作の不備を改善しました。
  • nmalloc_setmark1(), nmalloc_setmark2(), nmalloc_getmark(), nmalloc_getobjptr()がdeprecatedとなりました。将来のリリースで削除されます。
  • NMALLOC_HEAPOPTION_CHECK_0, NMALLOC_HEAPOPTION_CHECK_1がdeprecatedとなりました。将来のリリースで削除されます。
  • その他細かい変更と修正

2016-07-26

2016-06-29

2016-05-31

  • 次回リリースよりPC版で提供されるcygwin用のビルドは64bitとなり、ライブラリのディレクトリはlib/cmake/gccからlib/cmake/cygwinに変更されます。
  • nlib_remove(), nlib_thread_getname()が追加されました。
  • heapライブラリのheap::CentralHeap(nmalloc)の動作を改善しました。
    • 大きなサイズ(1MB以上)のメモリを割り当てた場合のフラグメンテーション問題を緩和しました。
    • 割り当てられるメモリアドレスの範囲が必要以上に大きくなっている問題を緩和しました。
  • その他細かい変更と修正

2016-04-26

  • Alpine Linux 3.3での動作確認を開始しました。
  • Ubuntu 16.04LTSでの動作確認を開始しました。これに伴いUbuntu 15.10での動作確認を終了しました。
  • Free BSD 10.3での動作確認を開始しました。これに伴いFree BSD 10.2での動作確認を終了しました。
  • heapライブラリのheap::CentralHeap(nmalloc)で比較的大きなサイズ(4KB以上)のメモリを割り当てた場合のフラグメンテーション問題を緩和しました。
    • 1MBytesまでの割り当てはフリーリスト内の区間にベストフィットするようにしました(従来は512KBytes)。
    • アライメントつき割り当ての場合にフラグメンテーションが発生しやすくなる問題を修正しました。
  • ossライブラリに収録されているSQLiteをバージョン3.12.2にアップデートしました。また、テンポラリファイルが削除されるようになりました。
  • CAFE版およびCTR版のnlib_fd_pwrite()およびnlib_fd_pread()において、ファイルサイズより大きいオフセットを指定した場合の動作を修正しました。
  • simd::I64がdeprecatedになりました。
  • Crc32クラスがdeprecatedになりました。nlib_crc32()またはnlib_crc32c()を利用してください。
  • その他細かい変更と修正

2016-03-29

2016-02-23

  • CAFE/CTR以外においてossライブラリがnmallocではなくnlib_mallocを利用するようになりました。
  • heapライブラリのnmalloc_query()の引数に、NMALLOC_QUERY_UNIFY_FREELISTを指定できるようになりました。
  • heapライブラリのCentralHeapが保持するヒープ内のメタデータの断片化を緩和しました。
  • simdライブラリにsimd::I128::PopCntMask8(), simd::I128::ClzMask8(), simd::I128::CtzMask8()を追加しました。
  • いくつかのヘッダファイルが抜け落ちていた問題を修正しました。
  • Windows版のDLLでnlib_malloc_size()が利用できない問題を修正しました。
  • その他細かい変更と修正

2016-01-26

  • CentOS 7.2での動作確認を開始しました。これに伴いCentOS 7.1での動作確認を終了しました。
  • Fedora 23での動作確認を開始しました。これに伴いFedora 22での動作確認を終了しました。
  • nlib_is_error()関数が追加されました。errno_tboolの戻り値に対して、エラー判定の記述を紛らわしくない形で行うことができます。
  • nlib_getenv()関数がCAFE及びCTRに対応しました。
  • 各クラスのIsOk(), IsError()関数がdeprecatedになりました。nlib_is_error()関数かoperator bool()関数を利用してください。
  • miscライブラリのUtf16InputStream, Utf32InputStream, WcharInputStream, Base64InputStream, Base64OutputStreamInit()メンバ関数が追加されました。
  • miscライブラリのTextReader, TextWriter, BinaryReader, BinaryWriterクラスの初期化がInit()Open()の2段階に分割されました。
  • exiライブラリ内のクラスのIsOk(), IsError(), Initialize(), GetErrorValue()メンバ関数がdeprecatedになりました。
  • heapライブラリ内のクラスのInitialize()メンバ関数がdeprecatedになりました。
  • msgpackライブラリのCsvReaderクラスの初期化がInit()Open()の2段階に分割されました。
  • nmalloc_aligned()で4096バイトより大きいアラインメントでメモリを割り当てると、クラッシュする場合がある不具合を修正しました。
  • nmalloc_query(NMALLOC_QUERY_MAX_ALLOCATABLE_SIZE, ...)が実際に割り当てられるサイズよりも大きいサイズを返す場合がある問題を修正しました。
  • simdライブラリのF128::StoreLoA4(), F128::StoreHiA4()がARM プロセッサ上での実行時にクラッシュする場合があるという問題を修正しました。
  • その他細かい変更と修正
こちらに 過去のChangelogs があります。