DataManager クラスで他言語から利用できる Sort() メソッドを公開
この場では、C++/CLI で作成したライブラリに、C# 言語で作成したメソッドを関数オブジェクトとして渡し、並び替えアルゴリズムで利用する例を作成します。
#include <cliext/vector> #include <cliext/algorithm> #using <mscorlib.dll> using namespace System; using namespace cliext; using namespace Microsoft::VisualC::StlClr; public ref class DataManager { private: vector<int>^ container; public: DataManager(int min, int max); void Sort(BinaryDelegate<int, int, bool>^ func); IVector<int>^ GetVector(); }; DataManager::DataManager(int min, int max) { container = gcnew vector<int>(); for (int i = min ; i < max ; i++) container->push_back(i); } void DataManager::Sort(BinaryDelegate<int, int, bool>^ func) { sort(container->begin(), container->end(), func); } IVector<int>^ DataManager::GetVector() { return container; }
Sample07 は、DataManager クラスが内部で保持する vector オブジェクトの要素を STL/CLR のアルゴリズムで用意されている sort() 関数を使って整列させる Sort() メソッドを公開しています。sort() 関数を他の言語から利用することはできないため、他の言語からは Sort() メソッドを使って DataManager が保有するコンテナの要素を整列させるものとします。このとき、Sort() メソッドは BinaryDelegate 型のデリゲートをパラメータとして受け取り、これを sort() 関数に渡します。こうすることで、他の言語で書かれたコードを STL/CLR のアルゴリズムに組み込むことができます。
デリゲートを利用して降順に並べる
次に、上で作成した Sample07 の Sort() メソッドに、BinaryDelegate<int, int, bool> 型のデリゲートを渡す C# 言語のコードを書きます。
using Microsoft.VisualC.StlClr; class Test { public static void Main(string[] args) { DataManager data = new DataManager(0, 10); IVector<int> vector = data.GetVector(); foreach (int value in vector) System.Console.Write(value + " "); System.Console.WriteLine(""); BinaryDelegate<int, int, bool> func = delegate(int arg1, int arg2) { System.Console.WriteLine("Arg1={0}, Arg2={1}", arg1, arg2); return (arg1 > arg2); }; data.Sort(func); foreach(int value in vector) System.Console.Write(value + " "); } }
0 1 2 3 4 5 6 7 8 9 Arg1=1, Arg2=0 Arg1=0, Arg2=1 Arg1=2, Arg2=1 Arg1=1, Arg2=2 Arg1=3, Arg2=2 Arg1=2, Arg2=3 Arg1=4, Arg2=3 Arg1=3, Arg2=4 Arg1=5, Arg2=4 Arg1=4, Arg2=5 Arg1=6, Arg2=5 Arg1=5, Arg2=6 Arg1=7, Arg2=6 Arg1=6, Arg2=7 Arg1=8, Arg2=7 Arg1=7, Arg2=8 Arg1=9, Arg2=8 Arg1=8, Arg2=9 9 8 7 6 5 4 3 2 1 0
Sample08 は、Sample07 の DataManager クラスをインスタンス化し Sort() メソッドに C# 言語側で用意した匿名メソッドを渡しています。デフォルトの状態では、DataManager が内部で生成したコンテナは 0 ~ 9 までの整数が昇順に並んでいます。そこで、Sort() メソッドに渡したデリゲートでは、降順に並べるように結果を返しています。デリゲートが呼び出されていることを確認するために、匿名メソッドは、渡されたパラメータを標準出力に表示します。Sort() メソッドを実行すると、正しくデリゲートが呼び出されていることが確認できます。
最後に
C++/CLI の主な役割は、ネイティブコードとマネージコードの橋渡しにあります。もちろん、純粋な .NET Framework アプリケーション開発用言語としても非常に強力な機能を備えていますが、多くのプロジェクトでは C# や Visual Basic が採用されています。しかし、これまで C++ プログラマが作ってきたソフトウェアや、培ってきた知識経験を再利用できるのは C++/CLI の大きな利点であることは言うまでもありません。そして、多くの C++ プログラマは STL を使ってコードを書いています。
.NET Framework では、System.Collections.Generic 名前空間にあるクラスを使うことで、特定の言語に依存せずに任意の数の要素を管理することができます。これに対して STL/CLR は C++/CLI に依存し、他の言語では利用できません。C++/CLI プログラマがどちらを使うべきかという問題には、いくつかの議論があると思います。ですが、本稿でご説明させていただいたように、生成された STL/CLR オブジェクトを他の言語から操作することは可能であり、ライブラリの内部で STL/CLR を使い、外部には IEnumerable 型として公開するような方法があります。IVector インターフェイスを通すような方法もご紹介しましたが、通常は、他の言語で STL を意識したコードを書くのは避けるべきです。
どちらにしても、STL/CLR が C++/CLI の世界だけで孤立しているものではなく、必要に応じて他のライブラリやアプリケーションとコラボレーションできることは重要です。STL の型に依存しない強力なプログラミングを、マネージ環境で応用してみてはいかがでしょうか。
