C++プロジェクトでNuGetを使ってみようよ!(Vol. 1:パッケージ導入編)

  • 63
    Like
  • 0
    Comment

こんにちはー!ニアです。
今回は、NuGetパッケージをC++プロジェクトに導入する方法について紹介していきます。

1. NuGetとは

NuGetとは、Visual Studioの拡張機能として付属しているライブラリのパッケージ管理システムです。
ライブラリの導入から、管理、アップデートまで簡単に行うことができる他、他のライブラリとの依存関係を自動的に解決することができます。

Visual Stuio 2013のNuGetパッケージマネージャー
n1-1.PNG

Visual Stuio 2015のNuGetパッケージマネージャー(バージョン3.0)
n1-1v14.PNG

Visual Stuio 2015 Update 1のNuGetパッケージマネージャー(バージョン3.3)
n1-1v14b.PNG

Visual Stuio 2017のNuGetパッケージマネージャー(バージョン4.0)
nuget.PNG

2. C++プロジェクトにNuGetパッケージをインストールしてみよう

「でも、NuGetは.NET Framework向けだから、C++メインの私には関係ないよね・・・」と思っている方、ちょっと待って!
バージョン2.5からC++プロジェクトもサポートされています。NuGetパッケージをインストールすると、煩わしいプロジェクトの設定(例:追加のインクルードディレクトリや追加のライブラリディレクトリの設定)を省くことができます。

ここでは、「Boost」のNuGetパッケージをインストールしていきます。

まずはC++のプロジェクトを作成(もしくはオープン)します。
C++のプロジェクト

ソリューションエクスプローラーからNuGetパッケージをインストールしたいプロジェクトを右クリックし、「NuGetパッケージの管理...」を選択します。
「NuGetパッケージ管理」の選択

NuGetパッケージマネージャーのダイアログが表示されたら、右上の検索ボックスに「boost」と入力します。検索結果から「boost-vc1201」を選択し、「インストール」ボタンをクリックします。
Boostの選択

Visual Stuio 2015の場合、パッケージリソースの下にある検索ボックス「boost」と入力します。検索結果から「boost-vc1401」を選択し、「インストール」ボタンをクリックします。
n1-4v14.PNG

Visual Stuio 2015 Update 1では、フィルタータブの下に検索ボックスがあります。
n1-4v14b.PNG

インストールが完了するまでしばらく待ちます(ちょっと時間がかかるかもしれません・・・)。
Boostのインストール中

Visual Studio 2015及びVisual Stuio 2015 Update 1の場合、出力ウィンドウに進捗状況が表示されます。
n1-5v14b.PNG

インストールが完了すると、そのNuGetパッケージの項目の右上にチェックマークが付きます。
インストール完了

n1-6v14.PNG

n1-6v14b.PNG

3. インストールしたBoostを使って、ちょっとプログラミング

せっかくBoostをインストールしたので、ちょっとプログラミングしてみたいと思います。

ここでは「ヒルベルト行列(Hilbert matrix)」を使って連立方程式を解いていきます。
コンピューター上で連立方程式の解を求める場合、ガウスの消去法やLU分解などを利用していくことになります。Boostでは、行列をLU分解する関数が用意されているので、それを使ってコーディングしていきます。

simultaneous_equations_with_hibert_matrix.cpp
#include <iostream>
#include "boost/numeric/ublas/matrix.hpp"
#include "boost/numeric/ublas/vector.hpp"
#include "boost/numeric/ublas/io.hpp"
#include "boost/numeric/ublas/triangular.hpp"
#include "boost/numeric/ublas/lu.hpp"

using namespace std;
using namespace boost::numeric;
using namespace boost::numeric::ublas;

int main( int argc, char* argv[] ) {

    // 連立方程式の次元数を入力します。
    int n;
    cout << "Dim. = ";
    cin >> n;
    if( n <= 0 ) return -1;

    // 行列とベクトルの変数宣言です。
    matrix<double> a( n, n ), a2( n, n );
    ublas::vector<double> b( n ), b2( n ), e( n );      // 注:std名前空間にもvector<T>クラスがあります。
    permutation_matrix<int> pm( a.size1() );

    // Hilbert行列を生成します。
    for( int i = 0; i < n; i++ ) {
        for( int j = 0; j < n; j++ ) {
            a( i, j ) = 1.0 / ( i + j + 1 );
            a2( i, j ) = a( i, j );     // Hilbert行列Aをバックアップしておきます。
        }

        // b[i] = Hilbert行列の対角成分、a[i][i] とします。
        b[i] = 1.0 / ( i * 2 + 1 );
        b2[i] = b[i];                   // ベクトルbをバックアップしておきます。
    }

    // Hilbert行列AとHilbert行列の対角成分のベクトルbを表示します。
    cout << "A = " << a << endl;
    cout << "b = " << b << endl;
    cout << endl;

    // Hilbert行列AをLU分解します。
    // ※aにLU分解後の行列が、pmにLU分解時の行の交換情報のベクトルが格納されます。
    lu_factorize( a, pm );
    // LU分解後の行列とLU分解時の行の交換情報のベクトルを表示します。
    cout << "A_LU = " << a << endl;
    cout << "pm = " << pm << endl;
    cout << endl;

    // Hilbert行列A( LU分解済み )、LU分解時の行の交換情報のベクトル、
    // Hilbert行列の対角成分のベクトルbから、解ベクトルを求めます。
    // ※bに解ベクトルが格納されます。
    lu_substitute( a, pm, b );
    // 解ベクトルを表示します。
    cout << "x = " << b << endl;
    cout << endl;

    // 求めた解ベクトルから式の誤差を求めます。
    e = b2 - prod( a2, b );
    cout << "Error = " << e << endl;

    return 0;
}

実行結果

Dim. = 5
A = [5,5]((1,0.5,0.333333,0.25,0.2),(0.5,0.333333,0.25,0.2,0.166667),(0.333333,0.25,0.2,0.166667,0.142857),(0.25,0.2,0.166667,0.142857,0.125),(0.2,0.166667,0.142857,0.125,0.111111))
b = [5](1,0.333333,0.2,0.142857,0.111111)

A_LU = [5,5]((1,0.5,0.333333,0.25,0.2),(0.333333,0.0833333,0.0888889,0.0833333,0.0761905),(0.5,1,-0.00555556,-0.00833333,-0.00952381),(0.2,0.8,-0.914286,0.000714286,0.00145125),(0.25,0.9,-0.6,0.5,-1.13379e-005))
pm = [5](0,2,2,4,4)

x = [5](5,-40,126,-160,70)

Error = [5](-1.77636e-015,-6.10623e-016,7.21645e-016,4.996e-016,-1.38778e-015)

4. インストールしたNuGetパッケージについて

インストールしたNuGetパッケージは基本的にソリューション単位で管理されています。そのため、インストール済みの同じNuGetパッケージはそのソリューション内にあるすべてのプロジェクトから利用することができます。似たようなプロジェクトはできるだけ同じソリューションに入れておくと、容量を節約することができます。
インストールしたNuGetパッケージ

ダウンロードや展開に時間がかかるNuGetパッケージも、2回目以降はソリューションにあるNuGetパッケージを追加するだけなので、その分速くインストールすることができます。
Boostを2つ目のプロジェクトにインストール

また、Visual Studio Onlineなどでソリューションをソース管理に追加すると、インストールしたNuGetパッケージも含めることができます。
インストールしたBoostもソース管理に追加

なお、ソリューションをフォルダーごと相手に渡しても大丈夫です!

5. NuGetパッケージをアンインストールする

ソリューションエクスプローラーからNuGetパッケージをアンインストールしたいプロジェクトを右クリックし、「NuGetパッケージの管理...」を選択します。
「NuGetパッケージ管理」の選択

NuGetパッケージマネージャーのダイアログが表示されたら、左のツリービューから「インストール済みのパッケージ」を選択し、右上の検索ボックスに「boost」と入力します。検索結果から「boost-vc1201」を選択し、「アンインストール」ボタンをクリックします。
Boostの選択

依存関係にあるパッケージもアンインストールするかどうかのメッセージが現れた場合、「はい(Y)」をクリックします。
依存関係のパッケージのアンインストール確認

Visual Stuio 2015の場合、フィルターから「インストール済み」を選択し、その下の検索ボックスに「boost」と入力します。検索結果から「boost-vc1401」を選択し、「アンインストール」ボタンをクリックします。
n1-9v14.png

依存関係にあるパッケージもアンインストールしたい時は、オプションにある「依存関係の削除」にチェックを入れます。
n1-10v14.PNG

Visual Stuio 2015 Update 1の場合、フィルタータブから「インストール済み」を選択し、その下の検索ボックスに「boost」と入力します。依存関係にあるパッケージもアンインストールしたい時は、アンインストールオプションにある「依存関係の削除」にチェックを入れます。
n1-10v14b.PNG

アンインストールが完了するまでしばらく待ちます。
Boostのアンインストール

アンインストールが完了すると、そのNuGetパッケージの項目の右上にあったチェックマークが消えます。

※複数のプロジェクトで同じNuGetパッケージを利用している場合、1つのプロジェクトからそのNuGetパッケージをアンインストールしても、パッケージそのものはソリューション内に残ります。利用しているすべてのプロジェクトからそのNuGetパッケージをアンインストールすると、パッケージそのものも削除されます。

6. インストール済みのNuGetパッケージをアップデートする

ソリューションエクスプローラーからNuGetパッケージをアップデートしたいプロジェクトを右クリックし、「NuGetパッケージの管理...」を選択します。
「NuGetパッケージ管理」の選択

NuGetパッケージマネージャーのダイアログが表示されたら、左のツリービューから「更新プログラム」を選択し、右上の検索ボックスに「boost」と入力します。

項目が見つかった場合、検索結果から「boost-vc1201」を選択し、「更新」ボタンをクリックします。
Boostの更新

Visual Stuio 2015の場合、フィルターから「アップグレードを利用可能」を選択し、その下の検索ボックスに「boost」と入力します。
n1-12v14.png

項目が見つからなかった場合、そのパッケージは最新版です。

Visual Stuio 2015 Update 1では、フィルタータブから「更新プログラム」を選択し、その下の検索ボックスに「boost」と入力します。
n1-12v14b.png

なお、アップデートが利用可能なパッケージがある場合、更新プログラムの項目の右側にパッケージの数が表示されます。

7. おわりに

C++プロジェクト向けのNuGetパッケージはBoostの他に、「OpenCV」や「Eigen」などもあります。自分が利用しているライブラリでもし、NuGetパッケージ版がリリースされていたら、インストールしてみてはいかがでしょう。

また、NuGetパッケージは自分で作成することもできます。Vol. 2以降では、NuGetパッケージを作成やNuGetギャラリーへのアップロード、NuGetのリポジトリにプライベートなサーバーにあるフォルダーを追加する方法などを紹介していきたいと思います。

それでは、See you next!

C++プロジェクトでNuGetを使ってみようよシリーズ一覧


  1. お使いのVisual Studioのバージョンによって、「vc***」の名前が異なります。Visual Studio 2010では「vc=100」、Visual Studio 2012では「vc=110」、Visual Studio 2013では「vc=120」、Visual Studio 2015では「vc=140」です。2017年3月8日現在、Visual Studio 2017用のパッケージ(vc=150?)はNuGetパッケージマネージャーにはありませんでした。