Thread Subject: how to pass a function from Matlab to mex file

Subject: how to pass a function from Matlab to mex file

From: Damian H

Date: 7 Aug, 2008 09:34:01

Message: 1 of 4

Hi there,

I'm new with mex and need your help. I want to use C
function (exactly amebsa.c routine) in MAtlab, but I don't
know how to pass a function from Matlab to mex file.

The code is quite long so i will put here only a part
concerning my mex problem.

All questions are listed from Q.1. to Q.6.
You can just answer i.e.:
 Q.1. It's easier than you could imagine...

or post correct mexFunction

------------------------------------------------------
My SSA.m file is a function:
-------------------------------------------------------

function [x,fval]=SSA(catalog,name)

//within this function I declare random values of x:
x = rand(8,1);

//then i have a subfunction, which takes an x, for this x
//calculates many others parameters and returns sum of
//squares of them.
function [SumOfSquares]=sse(x)

//I want to optimize my function sse(x) and use for this C
//function 'amebsa.c'.
//I call this function with many input parameters, also
//with my function sse(x).

[pb,yb]= amebsa(p, y, n_dim, TolFun, @sse, iter, Temp_begin);

//...
end
---------------------------------------------------
My mex gateway function amebsa.c
----------------------------------------------------
#include "mex.h"

//Instead of operation on arrays I use names:
/* Input Arguments */

#define simplex_vectors prhs[0]
#define f_begin_values prhs[1]
#define n_dimensions prhs[2]
#define convergence_tolerance prhs[3]
#define function prhs[4]
#define n_iterations prhs[5]
#define temperature prhs[6]

/* Output Arguments */

#define optimized_function plhs[0]
#define optimal_vector plhs[1]

// function amebsa

void amebsa(float **p, float y[], int ndim, float pb[],
float *yb, float ftol, float (*funk)(float []), int *iter,
float temptr)
{
//... is not important for this problem what's inside
}

//Now is my mexFunction, the problem is with a pointer
//float *funk, which needs to pass a pointer to my sse(x)
//function from Matlab to amebsa function.
//Q.1. How to do it?

void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray*prhs[] )
     
{
    float *p;
    float *y;
    int *ndim;
    float *pb;
    float *yb;
    float *ftol;

//Q.2.How to declare funk, so that it pass a
// float (*funk)(float [])??
    float *funk;
    int *iter;
    float *temptr;
    
    mwSize m,n;
    
    /* Create a matrix for the return argument */
    m = mxGetM(f_begin_values)-1;
    n = mxGetN(f_begin_values);
    optimal_vector = mxCreateDoubleMatrix(m, n, mxREAL);
    m = mxGetM(temperature);
    n = mxGetN(temperature);
    optimized_function = mxCreateDoubleMatrix(m, n, mxREAL);
    
    /* Assign pointers to the various parameters */
    p = (float*)mxGetPr(simplex_vectors);
    y = (float*)mxGetPr(f_begin_values);
    ndim = (int*)mxGetPr(n_dimensions);
    pb = (float*)mxGetPr(optimal_vector);
    yb = (float*)mxGetPr(optimized_function);
    ftol = (float*)mxGetPr(convergence_tolerance);

//Q.3.Should I use here mxGetPr?
//Q.4.'function' is not an array and mxGetPr returns only a
//double pointer (I can cast it to float pointer or integer
//pointer, but to pointer to float function(pointer to //float)?
//Q.5. Is there any solution how to deal with this problem?
//Q.6. How does the mex pass it right now? As what,
//structure? object?
    funk = (float*)mxGetPr(function);
    iter = (int*)mxGetPr(n_iterations);
    temptr =(float*)mxGetPr(temperature);
    
    /* Do the actual computations in a subroutine */
    amebsa(&p,y,*ndim,pb,yb,*ftol,funk,iter,temptr);
    return;
    
}
---------------------------------------------------------
When I try to compile a code written above:
--------------------------------------------------------
>> mex amebsa.c amotsa.c ran1.c nrutil.c
 
//I get:
Warning amebsa.c: 146 assignment of pointer to float
function(pointer to float) to pointer to float

//If i change declaration in mexFunction 'float *funk' to
float (*funk)(float [])

//and instead of 'funk = (float*)mxGetPr(function)'
funk = (float* (float //[]))mxGetPr(function)

//I get a message:
Error amebsa.c: 141 cast from `pointer to double' to
`pointer to float function(pointer to float)' is illegal
//(It's because mxGetPr returns only a double pointer)


!!!thanks a lot for looking at it!!!

Subject: how to pass a function from Matlab to mex file

From: James Tursa

Date: 9 Aug, 2008 06:19:01

Message: 2 of 4

"Damian H" <damiana@poczta.onet.pl> wrote in message
<g7efi9$o2$1@fred.mathworks.com>...
>
> Q.1. It's easier than you could imagine...
>

It's impossible to do what you are trying to do.

> //Q.1. How to do it?
>

You can't.

>
> //Q.2.How to declare funk, so that it pass a
> // float (*funk)(float [])??

You can't.

> ftol = (float*)mxGetPr(convergence_tolerance);
>
> //Q.3.Should I use here mxGetPr?

Yes you should use mxGetPr, but you shouldn't use (float *)
or floats. My guess is you are passing in doubles from
MATLAB, not singles (floats). So declare your variables as
double, not float. Don't use float anywhere.

> //Q.4.'function' is not an array and mxGetPr returns only a
> //double pointer (I can cast it to float pointer or integer
> //pointer, but to pointer to float function(pointer to
//float)?

Can't do this.

> //Q.5. Is there any solution how to deal with this problem?

Yes. See below.

> //Q.6. How does the mex pass it right now? As what,
> //structure? object?

It is passing it as a function_handle mxArray.

------------

Here are the details.

First, you cannot do what you are trying to do with the
function pointer in C, unfortunately. The value of a MATLAB
function_handle is a proprietary thing that has nothing
whatsoever to do with a C function pointer. i.e., there is
no way to take the MATLAB function_handle and somehow
retrieve an address for an entry point to that function in
memory and then use that in your C code. And even if you
could do this, you would not be passing float[] arrays to it
and returning float variables ... you would have to pass
mxArray pointers to it. So the whole architecture of what
you are trying to do will not work.

Having said that, you *can* call MATLAB functions from
within C code using the mexCallMATLAB function. You will
need to first convert the passed in function_handle to a
character string, and then convert any C arrays into
mxArrays, but it can be done. I have shown a simple example
below.

And why are you using float types in your C code instead of
double types in the first place? The default numeric type in
MATLAB is double, not float (single). Seems like you are
making an unnecessary complication here. And your own code
seems to be inconsistent anyway. For example, you use
rand(8,1) in one of your functions. This will produce a
double array. So if you are intending this to be passed into
the mex routine you better be expecting a double, not a float.

James Tursa

---------------------------------------------------

call this myfunction.m (the actual name is arbitrary):

function y = myfunction(x)
y = sqrt(x);
end

---------------------------------------------------

call this fhandletest.c:

// Performs y = fhandletest(@myfunction)
//
// Where: fhandletest is this file (i.e., mex fhandletest.c)
// myfunction is a MATLAB function or m-file that
takes a 1x5 double and
// produces one output. The actual name
of myfunction is
// arbitrary.

#include <string.h>
#include "mex.h"

// Gateway

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const
mxArray *prhs[])
{
    double d[] = {1.0, 2.0, 3.0, 4.0, 5.0};
    char *fname;
    mxArray *lhs[1], *rhs[1];
    
    if( nrhs != 1 )
        mexErrMsgTxt("Need 1 input argument\n");
    if( nlhs > 1 )
        mexErrMsgTxt("Only 1 output argument allowed\n");
    
    if( mxGetClassID(prhs[0]) == mxFUNCTION_CLASS ) {
        mexPrintf("detected function_handle\n");
        if( mexCallMATLAB(1, lhs, 1, prhs, "char") ) {
            mexErrMsgTxt("Unable to convert function handle
to name string\n");
        }
        fname = mxArrayToString(lhs[0]);
        mxDestroyArray(lhs[0]);
    } else if( mxIsChar(prhs[0]) ) {
        mexPrintf("detected char string\n");
        fname = mxArrayToString(prhs[0]);
    } else {
        mexErrMsgTxt("1st argument must be function handle
or name\n");
    }
    mexPrintf("function name is %s\n",fname);
    
    mexPrintf("creating input to function %s\n",fname);
    rhs[0] = mxCreateDoubleMatrix(1, 5, mxDOUBLE_CLASS, mxREAL);
    memcpy(mxGetPr(rhs[0]), d, sizeof(d));
    
    mexPrintf("calling %s\n",fname);
    if( mexCallMATLAB(1, plhs, 1, rhs, fname) ) {
        mexPrintf("Unable to call function %s\n",fname);
        mexErrMsgTxt(" ");
    }
    
// clean up temorary stuff
    mxDestroyArray(rhs[0]);
    mxFree(fname);
}

Subject: how to pass a function from Matlab to mex file

From: Ryan Ollos

Date: 1 Dec, 2008 21:42:01

Message: 3 of 4

"James Tursa" <aclassyguywithaknotac@hotmail.com> wrote in message <g7jcsl$qs0$1@fred.mathworks.com>...
> Having said that, you *can* call MATLAB functions from
> within C code using the mexCallMATLAB function. You will
> need to first convert the passed in function_handle to a
> character string, and then convert any C arrays into
> mxArrays, but it can be done. I have shown a simple example
> below.

I have found that it is also possible to use function handles by calling feval in mexCallMATLAB, which avoids the need to convert the function_handle to a character string. The mex function is:

/* mexFEval */

#include "mex.h"
   
void
mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
    /* Evaluate string in MATLAB workspace */
    if ( mxIsClass(prhs[0], "function_handle") )
        mexCallMATLAB(nlhs, plhs, nrhs, prhs, "feval");
    else
        mexErrMsgTxt("First Input is not a function handle.");
    
    return;
    
}

Then I can call it like this:

[outArg1, outArg2, ...] = mexEvalFunctionHandle(function_handle, inArg1, inArg2)

Subject: how to pass a function from Matlab to mex file

From: Ryan Ollos

Date: 1 Dec, 2008 21:55:03

Message: 4 of 4

Btw, I got the idea for this from the note at the end of this thread.
http://www.mathworks.com/support/bugreports/details.html?rp=334200

Tags for this Thread

Everyone's Tags:

mex

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
mex Damian H 7 Aug, 2008 05:35:06
rssFeed for this Thread
 

MATLAB Central Terms of Use

NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content. Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available via MATLAB Central. Read the complete Terms prior to use.

Contact us at files@mathworks.com