Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

.NET と MATLAB の間でのデータの変換

MATLAB® Compiler SDK™ 製品には、ネイティブのデータとコンパイルされた MATLAB 関数の間のデータ変換を容易にする MWArray アセンブリが用意されています。データ変換クラスの詳細については、MWArray API によるデータ マーシャリングを参照してください。

ネイティブの .NET データ型と MATLAB データ型の間でデータをマーシャリングする方法のガイドラインについては、以下の例を参照してください。

メモ

ターゲットまたは MATLAB のいずれかの環境を通過するだけのデータ オブジェクトについては、マーシャリングが不要な場合があります。特に、プロセス境界をまたがない場合は必要ありません。マーシャリングはコストが高いため、オンデマンドでのみ実行します。

手動での MATLAB 型へのキャスト

ネイティブ データ変換

MWNumericArray クラスのコンストラクターで System.Int32 引数を使用して、数値の定数を明示的に作成できます。その後、この変数を生成された .NET メソッドの 1 つに渡します。

int data = 24; MWNumericArray array = new MWNumericArray(data); Console.WriteLine("Array is of type " + array.NumericType);

この例を実行すると、結果は次のようになります。

Array is of type double 

ネイティブの整数 (int data) は、1 行 1 列の MATLAB double 配列を格納する MWNumericArray に変換されます。これは既定の MATLAB 型です。

整数の型を保持するには、自動変換を制御する機能を提供する MWNumericArray コンストラクターを使用します。

MWNumericArray array = new MWNumericArray(data, false);

多次元配列の処理

MATLAB と .NET では、多次元配列に対して実装されるインデックス方式が異なります。MWNumericArray 型の変数を作成すると、MATLAB で独自の内部インデックスを使用して同等の配列が自動的に作成されます。たとえば、MATLAB で使用されるインデックス方式は次のとおりです。

(row column page1 page2 ...)
一方、.NET のインデックスは次のようになります。
(... page2 page1 row column) 

次の多次元 MATLAB myarr について考えます。

>> myarr(:,:,1) = [1, 2, 3; 4, 5, 6]; 
>> myarr(:,:,2) = [7, 8, 9; 10, 11, 12]; 
>> myarr 

myarr(:,:,1) = 

     1     2     3 
     4     5     6 


myarr(:,:,2) = 

     7     8     9 
    10    11    12 

これと同等のコードを .NET で記述すると次のようになります。

double[,,] myarr = {{{1.000000, 2.000000, 3.000000}, {4.000000, 5.000000, 6.000000}}, {{7.000000, 8.000000, 9.000000}, {10.000000, 11.000000, 12.000000}}}; 

MWNumericArray の例

次のコード フラグメントは、double 値 (5.0) を MWNumericArray 型に変換する方法を示したものです。

MWNumericArray arraySize = 5.0; magicSquare = magic.MakeSqr(arraySize);

double 値を変換して変数 arraySize に代入した後、それ以上変換せずに、MATLAB ベースのメソッドで arraySize 引数を使用できます。この例では、MATLAB ベースのメソッドは magic.MakeSqr(arraySize) です。

配列の型の指定

特定の型の MATLAB 数値配列を作成する場合は、オプションの makeDouble 引数を False に設定します。これにより、作成される MATLAB 配列の型がネイティブの型から判定されるようになります。

次のコードでは、配列を MATLAB の 1 行 1 列の 16 ビット整数の配列として構成するように指定しています。

short data = 24; MWNumericArray array = new MWNumericArray(data, false); Console.WriteLine("Array is of type " + array.NumericType); 

この例を実行すると、結果は次のようになります。

Array is of type int16 

オプションの引数の指定

MATLAB では、vararginvarargout を使用して必須でない引数を指定できます。次の MATLAB 関数について考えます。

function y = mysum(varargin)
y = sum([varargin{:}]);

この関数は入力の和を返します。入力は varargin として提供されています。これは、呼び出し元から関数に任意の数の入力を指定できることを意味します。結果はスカラーの double 配列として返されます。

関数 mysum に対して、MATLAB Compiler SDK 製品では次のインターフェイスが生成されます。

// Single output interfaces public MWArray mysum() public MWArray mysum(params MWArray[] varargin) // Standard interface public MWArray[] mysum(int numArgsOut) public MWArray[] mysum(int numArgsOut, params MWArray[] varargin) // feval interface public void mysum(int numArgsOut, ref MWArray ArgsOut, params MWArray[] varargin)

varargin 引数は、MWArray[] または明示的な入力引数のリストとして渡すことができます。(C# では、メソッドの引数に params 修飾子を使用して、特定の型の任意の数のパラメーターをメソッドが受け入れるように指定します。)params を使用すると、カプセル化された MATLAB 関数に任意の数のオプション入力をコードで追加できます。

次に、.NET アプリケーションで mysum メソッドの単一の出力インターフェイスを使用する方法の例を示します。

static void Main(string[] args]) { MWArray sum= null; MySumClass mySumClass = null; try { mySumClass= new MySumClass(); sum= mySumClass.mysum((double)2, 4); Console.WriteLine("Sum= {0}", sum); sum= mySumClass.mysum((double)2, 4, 6, 8); Console.WriteLine("Sum= {0}", sum); } }

入力引数の数は可変です。

メモ

この特定のシグネチャでは、最初の引数を MWArray または整数以外の型に明示的にキャストする必要があります。これにより、このシグネチャが最初の引数として整数を受け取るメソッドのシグネチャと区別されます。最初の引数を MWArray または整数以外の型に明示的にキャストしないと、出力引数の数を表す引数として誤って解釈される可能性があります。

可変数の出力の引き渡し

varargout 引数がある場合、その処理方法は varargin 引数の処理と同じです。次の MATLAB 関数について考えます。

function varargout = randvectors()
for i=1:nargout
   varargout{i} = rand(1, i);
end

この関数は、i 番目のベクトルの長さが i に等しい、乱数の double ベクトルのリストを返します。この関数に対して、MATLAB Compiler SDK 製品では次の .NET インターフェイスが生成されます。

public void randvectors() public MWArray[] randvectors(int numArgsOut) public void randvectors(int numArgsOut, ref MWArray[] varargout)

この例では、標準のインターフェイスを使用して 2 つの出力引数をリクエストします。

MyVarargOutClass myClass = new MyVarargOutClass(); MWArray[] results = myClass.randvectors(2); Console.WriteLine("First output= {0}", results[0]); Console.WriteLine("Second output= {0}", results[1]);

入力引数の引き渡し

以下の例では、MATLAB 関数 myprimes の生成コードを示します。定義は次のとおりです。

function p = myprimes(n) 
p = primes(n);

単一の入力引数の構成

次のサンプル コードでは、入力引数として渡す dataMWNumericArray として構成しています。

MWNumericArray data = 5; MyPrimesClass myClass = new MyPrimesClass(); MWArray primes = myClass.myprimes(data);

ネイティブの .NET 型の引き渡し

この例では、ネイティブの double 型を関数に渡します。

MyPrimesClass myClass = new MyPrimesClass(); MWArray primes = myClass.myprimes((double)13);

MATLAB 関数の要件に従い、入力引数は MATLAB の 1 行 1 列の double 配列に変換されます。これは、ネイティブの double 型に対する既定の変換ルールです。サポートされるすべての .NET 型に対する既定のデータ変換については、.NET と MATLAB の間のデータ変換のルールを参照してください。

feval インターフェイスの使用

feval インターフェイスは、関数呼び出しの右辺で入力引数と出力引数の両方を渡します。出力引数 primes の前には ref 属性が必要です。

MyPrimesClassmyClass = new MyPrimesClass(); MWArray[] maxPrimes = new MWArray[1]; maxPrimes[0] = new MWNumericArray(13); MWArray[] primes = new MWArray[1]; myClass.myprimes(1, ref primes, maxPrimes); 

戻り値の型のクエリ

これまでの例は、出力引数の型と次元がわかっている場合に使用するガイドラインを示したものです。MATLAB のプログラミングでは、この情報が不明な場合や変わる場合もあります。この場合、メソッドを呼び出すコードで出力引数の型と次元のクエリが必要になることがあります。

クエリを行う方法は 2 つあります。

  • .NET リフレクションを使用して、任意のオブジェクトの型をクエリする。

  • MWArray クラスで提供されるいくつかのメソッドのいずれかを使用して、基となる MATLAB 配列についての情報をクエリする。

.NET リフレクション

"リフレクション" を使用すると、型のインスタンスの作成、既存のオブジェクトへの型のバインド、既存のオブジェクトからの型の取得を動的に実行できます。その後、その型のメソッドを呼び出したり、そのフィールドやプロパティにアクセスしたりできます。リフレクションの詳細については、MSDN ライブラリを参照してください。

次のコード サンプルでは、myprimes メソッドを呼び出し、リフレクションを使用して型を判別します。この例では、出力が数値ベクトルの配列として返されるものと想定していますが、正確な数値型はわかっていません。

 .NET リフレクションを使用した GetPrimes

この例では、toVector メソッドを使用して .NET プリミティブ型配列 (primesArray) を返します。これは、基となる MATLAB 配列を表します。この例で次のコード フラグメントを参照してください。

primes= myPrimesClass.myprimes((double)n); Array primesArray= ((MWNumericArray)primes). ToVector(MWArrayComponent.Real);

toVectorMWNumericArray クラスのメソッドです。列優先の順序で配列コンポーネントのコピーを返します。配列要素の型が数値配列のデータ型から判別されます。

MWArray クエリ

この例では、MWNumericArrayNumericType メソッドを MWNumericType 列挙と共に使用して、基となる MATLAB 配列の型を判別します。switch (numericType) ステートメントを参照してください。

 MWArray クエリを使用した GetPrimes

この例のコードでは、NumberOfDimensions を呼び出して次元も確認しています。次のコード フラグメントを参照してください。

if ((!primes.IsNumericArray) || (2 != primes.NumberofDimensions)) { throw new ApplicationException("Bad type returned by mwprimes"); }

この呼び出しは、配列が適切な次元の数値でない場合は例外をスローします。

オブジェクトの参照渡し

MWArray の特別なサブクラスである MWObjectArray で、.NET オブジェクトを参照する MATLAB 配列を作成できます。

MWObjectArray を使用して .NET オブジェクトの MATLAB コード ラッパーを作成できます。この手法は、オブジェクトを MATLAB 関数に参照で渡し、.NET オブジェクトを返すために使用します。このセクションの例で、いくつかの一般的な使用例を示します。

.NET オブジェクトを .NET アセンブリに渡す

オブジェクトを MATLAB Compiler SDK アセンブリに渡すには、次のようにします。

  1. .NET 型を参照する MATLAB 関数を記述します。

    function addItem(hDictionary, key, value)
    
           if ~isa(hDictionary,'System.Collections.Generic.IDictionary')
               error('foo:IncorrectType', 
                 ... 'expecting a System.Collections.Generic.Dictionary');
           end 
         
           hDictionary.Add(key, value);
     
         end

  2. MATLAB 関数に渡す .NET オブジェクトを作成します。

     Dictionary char2Ascii= new Dictionary(); char2Ascii.Add("A", 65); char2Ascii.Add("B", 66); 
  3. MWObjectArray のインスタンスを作成して .NET オブジェクトをラップします。

    MWObjectArray MWchar2Ascii= new MWObjectArray(char2Ascii); 
  4. ラップされたオブジェクトを MATLAB 関数に渡します。

    myComp.addItem(MWchar2Ascii,'C', 67); 

デプロイされた .NET アセンブリを使用して MATLAB 関数内のカスタム .NET オブジェクトを返す

MWObjectArray を使用して、MATLAB Compiler SDK .NET アセンブリ内にオブジェクトのクローンを作成できます。前の例に続いて、次の手順を実行します。

  1. .NET 型を参照する MATLAB 関数を記述します。

     function result= add(hMyDouble, value)
    
           if ~isa(hMyDouble,'MyDoubleComp.MyDouble')
              error('foo:IncorrectType', 'expecting a MyDoubleComp.MyDouble');
           end
           hMyDoubleClone= hMyDouble.Clone();
           result= hMyDoubleClone.Add(value);
     
         end
    
  2. オブジェクトを作成します。

    MyDouble myDouble= new MyDouble(75);
    
  3. MWObjectArray のインスタンスを作成して .NET オブジェクトをラップします。

    MWObjectArray MWdouble= new MWObjectArray(myDouble); origRef = new MWObjectArray(hash);

  4. ラップされたオブジェクトを MATLAB 関数に渡し、返されるクローン オブジェクトを取得します。

    MWObjectArray result= 
                (MWObjectArray)myComp.add(MWdouble, 25);
  5. .NET オブジェクトをアンラップし、結果を出力します。

    MyDouble doubleClone= (MyDouble)result.Object; Console.WriteLine(myDouble.ToDouble()); Console.WriteLine(doubleClone.ToDouble()); 

MWObjectArray のクローン

MWObjectArrayClone メソッドを呼び出すときは、ラップされたオブジェクトについて次のルールが適用されます。

  • ラップされたオブジェクトが ValueType の場合、そのオブジェクトがディープ コピーされます。

  • ValueType でないオブジェクトで ICloneable を実装した場合、そのオブジェクトの Clone メソッドが呼び出されます。

  • ラップされたオブジェクトでは MemberwiseClone メソッドが呼び出されます。

MWObjectArray aDate = new MWObjectArray(new DateTime(1, 1, 2010)); MWObjectArray clonedDate = aDate.Clone();

MWObjectArray を使用した最適化

MWObjectArray を使用して .NET オブジェクトへの参照を作成し、それをコンポーネントに渡す方法の完全な例については、目的関数との MATLAB 最適化ルーチンの統合を参照してください。

MWObjectArray とアプリケーション ドメイン

IIS にデプロイされる ASP .NET Web アプリケーションは、それぞれ個別の AppDomain で起動されます。

MWObjectArray でラップされた .NET 型は MATLAB .NET インターフェイスでサポートされていなければなりません。MWObjectArray を既定の AppDomain で作成する場合、ラップされた型について、それ以外の制限はありません。

MWObjectArray を既定の AppDomain 以外で作成する場合、ラップされた .NET 型はシリアル化可能でなければなりません。この制限が適用されるのは、既定以外の AppDomain から既定の AppDomain にオブジェクトをマーシャリングして、MATLAB からオブジェクトにアクセスする必要があるためです。

MWObjectArray の制限

C# コードにグローバル オブジェクトがある場合、アプリケーションの終了時に Windows® の例外を受け取ります。この制限に対処するには、次のいずれかの解決法を使用します。

  • アプリケーションを終了する前にグローバル オブジェクトを明示的にクリアする。

    globalObj.Destroy();

  • アプリケーションを終了する前に TerminateApplicationEx メソッドを呼び出す。

    MWMCR.TerminateApplicationEx();

    TerminateApplicationEx の詳細については、MWArray クラス ライブラリのリファレンスを参照してください。

複素数配列内の実数成分または虚数成分へのアクセス

成分の抽出

複素数配列 (実数と虚数の両方のデータで構成される配列) にアクセスする場合、既定では実数部と虚数部 (成分と呼ぶ) の両方を抽出します。次のメソッドの呼び出しでは、実数成分と虚数成分の両方が抽出されます。

MWNumericArray complexResult= complexDouble[1, 2];
該当する "成分インデックス" メソッドを呼び出して、複素数行列の実数成分または虚数成分のみを抽出することも可能です。

複素数数値配列の成分インデックス

非スパースの複素数数値配列から実数成分または虚数成分を返すには、MWArrayComponent.real メソッドまたは .imaginary メソッドを呼び出します。

complexResult= complexDouble[MWArrayComponent.Real, 1, 2]; complexResult= complexDouble[MWArrayComponent.Imaginary, 1, 2];

非スパースの複素数数値配列に実数成分または虚数成分を代入するには、MWArrayComponent.real メソッドまたは .imaginary メソッドを呼び出します。

matrix[MWArrayComponent.Real, 2, 2]= 5; matrix[MWArrayComponent.Imaginary, 2, 2]= 7:

Microsoft® Visual Studio® 8 以降では、スパースの複素数数値配列から実数成分または虚数成分を返すことができます。

complexResult= sparseComplexDouble[MWArrayComponent.Real, 4, 3]; complexResult = sparseComplexDouble[MWArrayComponent.Imaginary, 4, 3]; 

MATLAB 配列から .NET 配列への変換

MATLAB 配列を .NET 配列に変換するには、MWArrayComponent.real メソッドまたは .imaginary メソッドと共に toArray メソッドを呼び出します。

Array nativeArray_real= matrix.ToArray(MWArrayComponent.Real); Array nativeArray_imag= matrix.ToArray(MWArrayComponent.Imaginary);

MATLAB 配列から .NET ベクトルへの変換

MATLAB ベクトルを .NET ベクトル (単一次元の配列) に変換するには、MWArrayComponent.real メソッドまたは .imaginary メソッドを呼び出します。

Array nativeArray= sparseMatrix.ToVector(MWArrayComponent.Real); Array nativeArray= sparseMatrix.ToVector(MWArrayComponent.Imaginary); 

ジャグ配列の処理

"ジャグ配列" は、要素が配列である配列です。ジャグ配列の要素は、同じ次元とサイズの要素で構成される "非ジャグ配列" の要素とは異なり、次元やサイズが異なる場合があります。

特に Web サービスでは、ほぼ例外なくジャグ配列のデータを処理します。

MWNumericArray では、矩形形状のジャグ配列のみを処理できます。

次のコード スニペットでは、int 型の矩形のジャグ配列を初期化して取り込んでいます。

int[][] jagged = new int[5][]; for (int i = 0; i < 5; i++) jagged[i] = new int[10]; MWNumericArray jaggedMWArray = new MWNumericArray(jagged); Console.WriteLine(jaggedMWArray); 

関連するトピック