0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

シングルファイル C/C++ ライブラリの実装方法

Last updated at Posted at 2020-05-10

シングルファイル C/C++ ライブラリの概要や利点についてはこちら。
https://qiita.com/syoyo/items/e9d4aff56f691f5b783b

私の知る限りシングルファイルC/C++ライブラリの実装方法には以下の2種類がある(他にもあったら教えてほしい)。

なおシングルファイルC/C++ライブラリを使うメリットはどこでも簡単に動かせることだと思うので、この記事では移植性を損なうコンパイラの拡張機能を使うことは考えない。

#ifdefで宣言と実装を切り替える方法

1ファイルの中に宣言と実装を分けていれておき#ifdef FOO_IMPLEMENTATIONにより切り替える方法。

宣言されている関数を使う時は#includeして宣言を参照する。
実装したいファイルでは#define FOO_IMPLEMENTATION#includeの前に書き、実装を読み込む。
実装するのはプログラム内で唯一のファイルである必要がある。

この方法の代表的なライブラリとしてはstbtinyobjloaderがある。

この方法の問題はどこで実装するかをプログラマが意識してコントロールしなければならない点だ。
複数個所で実装すると当然リンク時に重複シンボルエラーになる。

この問題はシングルファイルC/C++ライブラリを使ったライブラリの移植性の低下につながる。

例えばライブラリAでstbを使っていた(実装していた)とする。
そのことを知らずに別途stbを実装しているアプリケーションBでライブラリAをリンクすると重複シンボルエラーになる。

template (or inline) で書く方法

こちらはC++限定になるがtemplateで書く方法。

この方法は#ifdefを使う方法よりも流行っていないようだが、例としてはNanoRTが挙げられる。
私自身もこの方法でNanoPMというPatchMatchのシングルファイルC/C++ライブラリを作ったことがある(名前はNanoRTをリスペクトしてつけた)。

#includeするだけで使えるので#ifdefを使う方法よりも扱いやすいと私は思う。

templateの問題としてコンパイル時間と実行ファイルサイズが増加する可能性がある。

また、プログラム全体でバージョンが統一されていないと実行時の挙動が予測できない。
あるtemplateライブラリのv0.1を使ったライブラリAと、v0.2を使ったライブラリBをリンクすると、同じ名前だが実装が異なるためどちらかのシンボルで上書きされ実行時の挙動が予測できない。

コンパイルとリンクが通ってしまい、さらに実行時も動いたり動かなかったりするのが厄介だ。
シングルファイルではないがEigenでこの問題によく悩まされる。

比較

#ifdef方式 template方式
言語 C/C++ C++のみ
コンパイル時間 普通 長め
実行ファイルサイズ 普通 大きめ
実装ファイルをプログラマが指定 する しない
重複シンボルエラー 起きやすい 起きにくい
実行時エラー 起きにくい 起きやすい

この表だけを見ると一長一短だが、#ifdef方式の実装ファイルをプログラマが指定するというのがだるすぎるので私はtemplate方式推しだ。

シングルファイルC/C++ライブラリを自作ライブラリに組み込むベストプラクティス

を知りたい。

前述したように単純に自作ライブラリに組み込むとリンクした際に#ifdef方式では重複シンボルエラー、template方式では実行時エラーになる可能性がある。

そこでgit submoduleなどで元のコードを参照するのではなく、コードを改変して自作ライブラリ名前空間に入れたり関数名に自作prefixをつけたりするのが安全だと思う。
が、改変が面倒だし元のコードのバージョンを保持しておくのも面倒なのでもっといい方法を探している。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?