CausMatlabStarten
Hier ist ein Beispielprogramm, mit dem aus einem Matlab Script eine vorkompilierte in C++ geschriebene Funktion ausgeführt wird.
Alle benötigten Dateien für dieses Beispiel sind auf matlab_c zu finden.
Das C Programm:
Interresant ist vorallem die Verwendung der Matlab Variablendeffinitionen, in mexFunction(). mexFunction() wird statt main() beim Aufruf des Programms gestartet! Hier findet die übersetzung der Matlab Variablen in C statt (mxGetScalar usw.). Es werden Pointer auf die Arrays für die Rückgabe an Matlab gesetzt (mxGetPr). Die Eigentliche Berechnung läuft in der Funktion rechnen(), sie ist natürlich vom zu lösenden Problem abhängig. Die C funktion wird mit dem Befehl mex funktionname.cc also in diesem Beispiel mex c_function.cc kompiliert. Es ist empfehlenswert Matlab mit dem Befehl matlab -check_malloc aus einem Terminal zu starten. Matlab überprüft dann automatisch ob ein pointer beim zugriff auf die "mex" Funktionen aus dem zugewiesenen speicher "rausläuft".
#include <mex.h> #include <stdio.h> #include <iostream> #include <stddef.h> #include <stdlib.h> #include <math.h> #include "nrutil.c" void rechnen(double **t,int m, int n, double a,int b, double *Obs1, double *Obs2); void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *t_m,a; int mrows,ncols,b; double **t; double *Obs1,*Obs2; /* Uebernehmen der Argumente die Matlab an diese C funktion uebergibt */ /* Create a pointer to the input matrix y. */ t_m = mxGetPr(prhs[0]); //pointer auf das feld t_m mrows = (int)mxGetM(prhs[0]); // anzahl der zeilen ncols = (int)mxGetN(prhs[0]); // anzahl der spalten /* Note: mxGetScalar returns a value, not a pointer. */ a = (double)mxGetScalar(prhs[1]); // a als flieskommazahl uebergeben b = (int)mxGetScalar(prhs[2]); // b als integer /* Matlab ?bergibt die Matritzen als eindimensionale felder */ /* Hier wird gezeigt, wie daraus wieder 2 dimensionale Arrays gemcht werden koennen*/ t = dmatrix(0,mrows,0,ncols); // mit nrutils.c funktion speicher allocieren for(int i=0; i<mrows; i++) { for(int j=0; j<ncols; j++) { t[i][j] = (*(t_m + i + j * mrows)); } } /* Matlab Ausgabe: Es werden zwei eindiemnsionale felder an Matlab zurueckgegeben */ /* Set the output pointer to the output matrix. */ plhs[0] = mxCreateDoubleMatrix(1,ncols, mxREAL); // erzeugt ein feld, in das geschrieben werden kann, mit der groesse mrows plhs[1] = mxCreateDoubleMatrix(1,ncols, mxREAL); /* Create a C pointer to a copy of the output matrix. */ Obs1 = mxGetPr(plhs[0]); // erster rueckgabenwert an Matlab Obs2 = mxGetPr(plhs[1]); // zweiter rueckgabenwert an Matlab /* Berechnungen */ rechnen(t,mrows,ncols,a,b,Obs1,Obs2); } // Hier wird die tatsaechliche berechnung gemacht void rechnen(double **t,int m, int n, double a,int b, double *Obs1, double *Obs2) { for(int j=0;j<n;j++) // alle spalten { Obs1[j] = 0; Obs2[j] = 0; for(int i=0;i<m;i++) //alle zeilen { Obs1[j] += t[i][j] ; //Summe der spalte Obs2[j] += t[i][j] / (double)b * a; //(Summe der spalte) / b * a // std::cout << t[i][j] <<'\n'; // moegliche testausgabe der werte } } }
Hier das aufrufende Matlab script:
M = rand(2,10); a = 5.3; b = 2; [O,O2] = c_function(M,a,b); % <--- hier die C++ Funktion disp('Matrix'); disp(M); disp('Summe der Spalten'); disp(O); disp(['Summe der Spalten mit ',num2str(a), ' multimpliziert und mit ',num2str(b), ' dividiert']); disp(O2);