matlab呼び出しCプログラム

12696 ワード

時間のかかる関数をc言語で実現しmex関数にコンパイルすることで実行速度を速めることができる.
Matlab自体はc言語のコンパイラを持たないので、VC、BC、Watcom Cのいずれかがマシンにインストールされていることを要求します.
Matlabをインストールするときにコンパイラを設定した場合は、mexコマンドを使用してc言語のプログラムをコンパイルすることができます.
選択しなかった場合は、Matlabにmex-setupと入力します.以下はヒントに従って一歩一歩設定すればいいです.
 
パスの設定が正しいかどうかをテストするために、次のプログラムをhelloとして保存します.c.
/*hello.c*/
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ mexPrintf("hello,world!/n"); 
} 

君がハローをcはC:/TEST/の下に置いてあり、MatlabでCD C:/TEST/現在のディレクトリをC:/TEST/に変更(注意、C:/TEST/のみを検索パスに追加するのは役に立たない).今ノック:mex hello.cすべてが順調であれば、コンパイルはコンパイラのヒント情報が現れた後に正常に終了するはずです.もしあなたがC:/TEST/を検索パスに追加したら、今helloを入力すると、プログラムはスクリーンに1行を打つことができます:hello,world!
プログラム全体は1つのインタフェースサブプロシージャmexFunctionによって構成される.void mexFunction(int nlhs,mxArray*plhs[],int nrhs,const mxArray*prhs[])前述したように、Matlabのmex関数には一定のインタフェース仕様があり、nlhs:出力パラメータ数plhs:出力パラメータを指すポインタnrhs:入力パラメータ数例えば[a,b]=test(c,d,e)を使用してmex関数testを呼び出す場合、testに渡されるこの4つのパラメータはそれぞれ2,plhs,3,prhsのうち:prhs[0]=c prhs[1]=d prhs[2]=e関数が戻るとplhs[0],plhs[1]のアドレスをaとbに割り当て、データを返す目的を達成する.注意深いあなたは、prhs[i]とplhs[i]がタイプmxArrayタイプのデータを指すポインタであることに気づいたかもしれません.このタイプはmexです.hで定義されているが,実際にはMatlabでは多くのデータがこのようなタイプで存在する.もちろん他のデータ型もありますが、Apiguideを参照してください.pdfの紹介. 
 
//hello.c 2.0 
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
int i; 
i=mxGetScalar(prhs[0]); 
if(i==1) 
  mexPrintf("hello,world!/n"); 
else 
  mexPrintf("   !/n"); 
}

このプログラムをコンパイルすると、hello(1)が実行され、画面に「hello,world」が表示されます.ハロー(0)は「こんにちは」を手に入れます.
1つの関数:mxGetScalarが使用され、呼び出し方法は以下の通りである:i=mxGetScalar(prhs[0]);「Scalar」はスカラーの意味です.Matlabにはデータが配列として存在し、mxGetScaleの役割はprhs[0]を介して渡されたmxArrayタイプのポインタが指すデータ(スカラー)をCプログラムの変数に与えることである.この変数は本来doubleタイプのはずであり、強制タイプ変換によって整形変数iに与えられる.
 
//hello.c 2.1 
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[], 
int nrhs, const mxArray *prhs[]) 
{ 
int *i; 
i=mxGetPr(prhs[0]); 
if(i[0]==1) 
  mexPrintf("hello,world!/n"); 
else 
  mexPrintf("   !/n"); 
} 

 
このようにmxGetPr関数によりmxArray型データを指すprhs[0]からdouble型を指すポインタが得られる.しかし、単一のデータではなくベクトルやマトリクスが入力された場合、どのように処理すればよいのかという問題もあります.mxGetPrではこの行列を指すポインタしか得られず,この行列の正確な大きさを知らなければ計算できない.この問題を解決するために,Matlabは,伝達パラメータの行数と列数を求める2つの関数mxGetMとmxGetNを提供する.次のルーチンの機能は簡単です.入力マトリクスを取得し、画面に表示します.
//show.c 1.0 
#include "mex.h" 
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ 
double *data; 
int M,N; 
int i,j; 
data=mxGetPr(prhs[0]); //          
M=mxGetM(prhs[0]); //        
N=mxGetN(prhs[0]); //        
for(i=0;i<M;i++) 
{   for(j=0;j<N;j++) 
     mexPrintf("%4.3f  ",data[j*M+i]); 
     mexPrintf("/n"); 
  }
} 

 
コンパイルが完了したら、a=1:10;   b=[a;a+1];show(a)show(b)では,Matlabではマトリクスの1行目が1から始まるのに対し,C言語では1行目のシーケンス数がゼロであり,Matlabのマトリクス要素b(i,j)はCの1次元配列大dataに伝達された後にdata[j*M+i]に対応する.入力データは関数呼び出し前にMatlabにメモリを申請していたが,mex関数はMatlabと同じアドレス空間を共有しているためprhs[]にポインタを渡すことでパラメータ伝達の目的を達成できる.しかし、出力パラメータはmex関数内でメモリ領域を申請してplhs[]にポインタを渡す必要があります.戻りポインタタイプはmxArrayでなければならないため、Matlabはメモリの申請を実現するためにmxCreateDoubleMatrixを専門に提供している.関数の原型は以下の通りである:mxArray*mxCreateDoubleMatrix(int m,int n,mxComplexity ComplexFlag)m:申請待ち行列の行数n:申請待ち行列の列数がマトリクス申請メモリの後、得られたのはmxArrayタイプのポインタで、plhs[]に入れて伝えることができます.しかし,この新しい行列の処理を関数内で行うには,前述したmxGetPrを用いる必要がある.mxGetPrを用いてこの行列中のデータ領域を指すポインタ(doubleタイプ)を取得すると、この行列に対して様々な操作や演算が可能となる.
 
 
//reverse.c 1.0 
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[], 
    int nrhs, const mxArray *prhs[]) 
{ 
double *inData; 
double *outData; 
int M,N; 
int i,j; 
inData=mxGetPr(prhs[0]); 
M=mxGetM(prhs[0]); 
N=mxGetN(prhs[0]); 
plhs[0]=mxCreateDoubleMatrix(M,N,mxREAL); 
outData=mxGetPr(plhs[0]); 
for(i=0;i<M;i++) 
  for(j=0;j<N;j++) 
   outData[j*M+i]=inData[(N-1-j)*M+i]; 
} 

 
もちろん、Matlabで使われているのはdoubleタイプというマトリクスだけではなく、文字列タイプ、疎マトリクス、構造タイプマトリクスなど、対応する処理関数も提供されています.本文はmexプログラムを作成する中で最もよく出会ういくつかの関数を用いて、残りの詳細はApirefを参照する.pdf.前の2つの部分の紹介を通じて、パラメータの入力と出力方法について基本的な理解があるはずです.これらの知識があれば,一般的なプログラミングニーズを満たすことができる.しかし、これらのプログラムにはまだ小さな欠陥があり、先に紹介したreは、前のルーチンで入力、出力パラメータの数、タイプをチェックしていないため、プログラムの許容誤差性が悪く、以下のプログラムは許容誤差性が良い.
#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[],  int nrhs, const mxArray *prhs[]) 
{ 
double *inData; 
double *outData; 
int M,N; 
//     
//     
if(nrhs!=1) 
    mexErrMsgTxt("USAGE: b=reverse(a)/n"); 
  if(!mxIsDouble(prhs[0])) 
   mexErrMsgTxt("the Input Matrix must be double!/n"); 
   inData=mxGetPr(prhs[0]); 
   M=mxGetM(prhs[0]); 
   N=mxGetN(prhs[0]); 
   plhs[0]=mxCreateDoubleMatrix(M,N,mxREAL); 
   outData=mxGetPr(plhs[0]); 
   for(i=0;i<M;i++) 
     for(j=0;j<N;j++) 
     outData[j*M+i]=inData[(N-1-j)*M+i]; 
  } 

 
上記の異常処理では,mexErrMsgTxtとmxIsDoubleの2つの新しい関数を用いた.MexErrMsgTxtは、エラーメッセージを与えながら現在のプログラムの実行を終了する.MxIsDoubleは、mxArrayのデータがdoubleタイプかどうかを判断するために使用されます.もちろんMatlabは他のデータ型を判断するための多くの関数も提供しているが,ここでは詳細を省略する.なお、Matlabが提供するAPIでは、関数接頭辞はmex−とmx−の2種類がある.mx-接頭辞付きの多くは、mxIsDouble、mxCreateDoubleMatrixなどのmxArrayデータを操作する関数です.一方,mx接頭辞付きのものは,mexPrintf,mxErrMsgTxtなど,Matlab環境と対話する関数が多い.それを理解しましたApiref.pdfで必要な関数を検索するのに役立ちます.これまで,Cを用いてmex関数を記述する基本手順を紹介した.