Announce

PukiWiki contents have been moved into SONOTS Plugin (20070703)

Matlab C Shared Library (Call Your Own Matlab Functions)

Table of Contents

Abstract

mcc enables you to call your own matlab functions from C.

Compile .m and create .dll so that C can call matlab functions

Instruction

Generate C routines from .m files using mcc

Create a directory where you will store generated library files by mcc. Let yourtoolpath be the path.

I create a library libpca from my own matlab function files, cvPca.m (Principal Component Analysis), cvPcaProj.m (Project onto PCA subspace), and cvPcaInvProj.m (Back project from PCA subspace) as an example.

mcc -W lib:libpca -T link:lib cvPca.m cvPcaProj.m cvPcaInvProj.m  -d yourtoolpath

This generates libpca.lib, libpca.h, and so on in the yourtoolpath and it enables to call these functions by mlfXxx in C such as mlfCvPca, mlfCvPcaProj, mlfCvPcaInvProj for cvPca.m, cvPcaProj.m, cvPcaInvProj.m respectively.

Set up your compiler -- MS Visual Studio's case

Open MS Visual Studio

  • Tools > Options > Projects and Solutions > VC++ directories >
  • Show Directory for: > Include Files. Now add
    yourtoolpath
  • Show Directory for: > Library Files. Now add
    yourtoolpath

Set Windows System Environment

  • Control Panel > System > Advanced > Environment Variables
  • Find 'Path' and Edit. Now add
    ;yourtoolpath
  • Reboot

Tips: To set system environment without rebooting, install SUPTOOLS.MSI from Windows XP Installer CD, then use

setx PATH %PATH%;yourtoolpath\lib

on cmd.exe.

Example

Build and run.

// required libraries to link
#ifdef _MSC_VER // if MS Visual C++
#pragma warning(push)
#pragma warning(disable:4996)
#pragma comment(lib, "libdfblas.lib")
#pragma comment(lib, "libdflapack.lib")
#pragma comment(lib, "libemlrt.lib")
#pragma comment(lib, "libeng.lib")
#pragma comment(lib, "libfixedpoint.lib")
#pragma comment(lib, "libmat.lib")
#pragma comment(lib, "libmex.lib")
#pragma comment(lib, "libmwblas.lib")
#pragma comment(lib, "libmwlapack.lib")
#pragma comment(lib, "libmwmathutil.lib")
#pragma comment(lib, "libmwservices.lib")
#pragma comment(lib, "libmx.lib")
#pragma comment(lib, "libut.lib")
#pragma comment(lib, "mclcom.lib")
#pragma comment(lib, "mclcommain.lib")
#pragma comment(lib, "mclmcr.lib")
#pragma comment(lib, "mclmcrrt.lib")
#pragma comment(lib, "mclxlmain.lib")
#pragma comment(lib, "libpca.lib")
#endif

#include "libpca.h"
#include <stdio.h>
#include "mex.h"

void display(const mxArray* in);
int run_main(int argc, char **argv);

int run_main(int argc, char **argv)
{
    double data[] = {1,2,3,4,5,6,7,8,9};
    mxArray *Dat, *M; // input
    mxArray *V = NULL, *Me = NULL, *Lambda = NULL; // output
    //Output arguments must be initialized by NULL    

    /* Call the mclInitializeApplication routine. 
     * Make sure that the application
     * was initialized properly by checking the return status. 
     * This initialization has to be done before calling any 
     * MATLAB API's or MATLAB Compiler generated
     * shared library functions.  */
    if( !mclInitializeApplication(NULL,0) )
    {
        fprintf(stderr, "Could not initialize the application.\n");
    	return -1;
    }
    
    /* Create the input data */
    Dat = mxCreateDoubleMatrix(3,3,mxREAL);
    memcpy(mxGetPr(Dat), data, 9*sizeof(double));
    M   = mxCreateDoubleScalar(1);
    
    /* Call the library intialization routine and make sure that the
     * library was initialized properly. */
    if (!libpcaInitialize()){
        fprintf(stderr,"Could not initialize the library.\n");
        return -2;
    }
    else
    {
        mlfCvPca(2, &V, &Me, &Lambda, Dat, M);
        display(V);
        
        /* Call the library termination routine */
        libpcaTerminate();
        
        /* Free the memory created */
        mxDestroyArray(V);
        mxDestroyArray(Me);
        mxDestroyArray(Lambda);
        mxDestroyArray(Dat);
        mxDestroyArray(M);
    }

    /* Note that you should call mclTerminate application 
     * at the end of your application.
     */
    mclTerminateApplication();
    return 0;
}

/**
 * This is nothing but a utility function.
 *
 * display the double matrix stored in an mxArray.
 * This function assumes that the mxArray passed as input 
 * contains double array.
 */
void display(const mxArray* in)
{
    int i=0, j=0;    /* loop index variables */
    int r=0, c=0;   /* variables to store the row and 
                         * column length of the matrix */
    double *data; /* variable to point to the double
                         * data stored within the mxArray */

    /* Get the size of the matrix */
    r = mxGetM(in);
    c = mxGetN(in);
    /* Get a pointer to the double data in mxArray */
    data = mxGetPr(in);
    
    /* Loop through the data and display the same in matrix format */
    for( i = 0; i < c; i++ ){
        for( j = 0; j < r; j++){
            printf("%4.2f\t",data[j*c+i]);
        }
        printf("\n");
    }
    printf("\n");
}

/**
 * Call "run_main" function using mclRunMain 
 * for Mac OSX compatibility.
 */
int main()
{
    mclmcrInitialize();
    return mclRunMain((mclMainFcnType)run_main,0,NULL); 
}

Example 2

Assemble initialization steps into one function, so do termination steps.

// required libraries to link
#ifdef _MSC_VER // if MS Visual C++
#pragma warning(push)
#pragma warning(disable:4996)
#pragma comment(lib, "libdfblas.lib")
#pragma comment(lib, "libdflapack.lib")
#pragma comment(lib, "libemlrt.lib")
#pragma comment(lib, "libeng.lib")
#pragma comment(lib, "libfixedpoint.lib")
#pragma comment(lib, "libmat.lib")
#pragma comment(lib, "libmex.lib")
#pragma comment(lib, "libmwblas.lib")
#pragma comment(lib, "libmwlapack.lib")
#pragma comment(lib, "libmwmathutil.lib")
#pragma comment(lib, "libmwservices.lib")
#pragma comment(lib, "libmx.lib")
#pragma comment(lib, "libut.lib")
#pragma comment(lib, "mclcom.lib")
#pragma comment(lib, "mclcommain.lib")
#pragma comment(lib, "mclmcr.lib")
#pragma comment(lib, "mclmcrrt.lib")
#pragma comment(lib, "mclxlmain.lib")
#pragma comment(lib, "libpca.lib")
#endif

#include "libpca.h"
#include <stdio.h>
#include "mex.h"

void display(const mxArray* in);
int mxInitialization();
int mxTermination();

int mxInitialization()
{
    mclmcrInitialize();

    /* Call the mclInitializeApplication routine. 
     * Make sure that the application
     * was initialized properly by checking the return status. 
     * This initialization has to be done before calling any 
      * MATLAB API's or MATLAB Compiler generated
     * shared library functions.  */
    if( !mclInitializeApplication(NULL,0) )
    {
        fprintf(stderr, "Could not initialize the application.\n");
    	return -1;
    }

    /* Call the library intialization routine and make sure that the
     * library was initialized properly. */
    if (!libpcaInitialize()){
        fprintf(stderr,"Could not initialize the library.\n");
        return -2;
    }
    return 0;
}

int mxTermination()
{
    /* Call the library termination routine */
    libpcaTerminate();

    /* Note that you should call mclTerminate application at the end of
    * your application.
    */
    mclTerminateApplication();

    return 0;
}

int main(int argc, char **argv)
{
    int err;
    if ( (err = mxInitialization()) != 0) {
        return err;
    }

    mxArray *Dat, *M; // input 
    mxArray *V = NULL, *Me = NULL, *Lambda = NULL; // output
    // Output arguments must be initialized with NULL.
    
    double data[] = {1,2,3,4,5,6,7,8,9};

    
    /* Create the input data */
    Dat = mxCreateDoubleMatrix(3,3,mxREAL);
    memcpy(mxGetPr(Dat), data, 9*sizeof(double));
    M   = mxCreateDoubleScalar(1);
    
    mlfCvPca(2, &V, &Me, &Lambda, Dat, M);
    display(V);

    /* Free the memory created */
    mxDestroyArray(V);
    mxDestroyArray(Me);
    mxDestroyArray(Lambda);
    mxDestroyArray(Dat);
    mxDestroyArray(M);

    if ( (err = mxTermination()) != 0) {
        return err;
    }
    return 0;
}

/**
 * This is nothing but a utility function.
 *
 * display the double matrix stored in an mxArray.
 * This function assumes that the mxArray passed as input 
 * contains double array.
 */
void display(const mxArray* in)
{
    int i=0, j=0;    /* loop index variables */
    int r=0, c=0;   /* variables to store the row and 
                         * column length of the matrix */
    double *data; /* variable to point to the double
                         * data stored within the mxArray */

    /* Get the size of the matrix */
    r = mxGetM(in);
    c = mxGetN(in);
    /* Get a pointer to the double data in mxArray */
    data = mxGetPr(in);
    
    /* Loop through the data and display the same in matrix format */
    for( i = 0; i < c; i++ ){
        for( j = 0; j < r; j++){
            printf("%4.2f\t",data[j*c+i]);
        }
        printf("\n");
    }
    printf("\n");
}

Mcc and Compilers Compatibility Table

MatlabMS VC++gccBorland
2008b (7.7)up to 2008
2008a (7.6)
2007b (7.5)up to 2005?
2007a (7.4)
2006b (7.3)
2006a (7.2)
R14SP3 (7.1)up to 7.1

Reference