Jazyk C v Matlabu

Cíle

Cílem semináře je naučit se vytvořit jednoduchý program v C, který bude spolupracovat s Matlabem.

C, C++ a Matlab

Programy psané v Matlabu lze kombinovat s programy v jazycích C a C++. Pomocí rozšiřujícího modulu Matab Coder lze programy napsané v Matlabu přeložit do jazyka v C nebo C++. Pro programy psané v C/C++ Matlab poskytuje rozhraní, pomocí kterého lze používat některé Matlabovské funkce v C/C++ a dále je možné programy napsané v C/C++ do Matlabu přeložit.

My si ukážeme druhý způsob, tedy jak použít programy napsané v C/C++ v Matlabu. Pro jednoduchost použijeme pouze jazyk C, nicméně pro C++ je princip podobný.

Kromě C a C++ pak umožňuje Matlab spolupráci s i dalšími jazyky, například Pythonem. Přehled těchto jazyků a možnost jejich spolupráce s Matlabem jsou zde.

Rozhraní pro spolupráci s Matlabem v C

Pro spolupráci s Matlabem v C jsou k dispozici různá rozhraní. Rozhraní C MEX API obsahuje základní funkce. Dále například rozhraní C Matrix API obsahuje funkce pro práci s maticemi, mimo jiné například obsahuje funkce, které umožňují získat přímo pointer na místa v paměti, ve které jsou uloženy dané matice v Matlabu.

Pro použití funkcí z daného rozhraní stačí vložit příslušný hlavičkový soubor. Tedy například #include "mex.h" pro rozhraní C MEX API nebo #include "matrix.h" pro rozhraní C Matrix API.

Standardně v jazyce C každý program musí obsahovat funkci main, která se volá při startu programu. Při programování funkcí nebo skriptů v C pro použití v Matlabu má podobný účel funkce mexFunction. Tedy tato funkce slouží jako vstupní bod. Funkce je v rozhraní C MEX API.

Následující příklad je převzatý z dokumentace a pro účely semináře zjednodušený. Výsledná funkce implementuje násobení vektoru skalárem.

/*
* arrayProduct.c - example in MATLAB External Interfaces
*
* Multiplies an input scalar (multiplier)
* times a 1xN matrix (inMatrix)
* and outputs a 1xN matrix (outMatrix)
*
* The calling syntax is:
*
* outMatrix = arrayProduct(multiplier, inMatrix)
*
* This is a MEX file for MATLAB.
*/

#include "mex.h"
#include "matrix.h"

void arrayProduct(double x, double *y, double *z, int n)
{
    int i;

    for (i=0 ; i<n; i++) {
        z[i] = x * y[i];
    }
}

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    double multiplier;    /* input scalar */
    double *inMatrix;     /* 1xN input matrix */
    mwSize ncols;         /* size of matrix */
    double *outMatrix;    /* output matrix */

    /* get the value of the scalar input */
    multiplier = mxGetScalar(prhs[0]);

    /* create a pointer to the real data in the input matrix */
    inMatrix = mxGetPr(prhs[1]);

    /* get dimensions of the input matrix */
    ncols = mxGetN(prhs[1]);

    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(1,ncols,mxREAL);

    /* get a pointer to the real data in the output matrix */
    outMatrix = mxGetPr(plhs[0]);

    /* call the computational routine */
    arrayProduct(multiplier,inMatrix,outMatrix,ncols);
}

Pokud tedy zdrojový kód uložíme do souboru s názvem arrayProduct.c a přeložíme jej (viz dále), můžeme pak přímo v Matlabu použít funkci arrayProduct:

s = 5;
A = [1.5, 2, 9];
B = arrayProduct(s,A)

Překlad pomocí příkazu mex

Pro kompilaci programů v C slouží příkaz mex. Výstupem je soubor ve formátu MEX. Se soubory v tomto formátu pak můžeme již pracovat jako se skripty nebo funkcemi napsanými přímo v Matlabu.

Před použitím je nutné nutné určit kompilátor, který se má pro překlad použít. Na našem serveru pro překlad z C máme k dispozici překladač MinGW64. Přímo v Matlabu tedy uložíme cestu k tomuto překladači následujícím příkazem:

setenv('MW_MINGW64_LOC',"C:\mingw\mingw64")

A dále zadáním příkazu mex -setup c zkonrolujeme, zda je opravdu opravdu vybrán překladač MinGW64.

Cestu je nutné nastavit při každém zapnutí Matlabu znovu. Šlo by samozřejmě provést takové nastavení, aby cesta byla uložena trvale, to ale provádět nebudeme.

Příkaz mex voláme přímo z příkazové rádky (Command Window) Matlabu. Nejjednodušší možnost je zadat jej s jedním argumentem, kterým je název souburu obsahující zdrojový kód v C:

mex functionInC.c