How can I run my first Mex function?

1 vue (au cours des 30 derniers jours)
ttopal
ttopal le 31 Mai 2018
Commenté : James Tursa le 4 Juin 2018
Hi,
I am trying to run a part of my matlab code in c++.
I am working with Matlab2018a, downloaded and installed mingw-w64 c/c++ compiler from the add on menu. i did set up by
mex -setup
mex -setup cpp
After number of corrections, I have this code:
#include "mex.h"
#include <iostream>
#include <stdlib.h>
#include <complex>
using namespace std;
/* computational subroutine */
void myMexFunction(const mxArray * lambda,const mxArray * ll_n, mxArray * output,
int N)
{
mwSignedIndex n,s,r;
mwSignedIndex M = N/2-1;
mwSignedIndex M1 = M+1;
mwSignedIndex c,d,rmin,rmax;
mexPrintf("M%d\n", M);
/* get pointers to the arrays */
mxDouble * lam = mxGetDoubles(lambda);
mxComplexDouble * lln = mxGetComplexDoubles(ll_n);
mxComplexDouble * out = mxGetComplexDoubles(output);
mexPrintf("inside the function\n");
/* perform the nestedloop op */
for(n = -M; n < M; ++n){
mexPrintf("inside the first loop\n");
c = min(M-n,M);
mexPrintf("c %d\n", c);
d = max(-M,-M-n);
mexPrintf("d %d\n", d);
for(s = -M; s < M; ++s){
mexPrintf("inside the second loop\n");
rmin=max(s-M,d);
rmax=min(s+M,c);
mexPrintf("rmin %d\n", rmin);
mexPrintf("rmax %d\n", rmax);
for(r= rmin; r<rmax; ++r){
mexPrintf("inside the third loop\n");
out[1].real=1;
out[2].imag=1;
// out[N*(s+M)+(n+M1)].real =
// out[N*(s+M)+(n+M1)].real + (lln[s-r+M1].real * lln[n+r+M1].real - lln[s-r+M1].imag * lln[n+r+M1].imag)*lam[r+M1];
// out[N*(s+M)+(n+M1)].imag =
// out[N*(s+M)+(n+M1)].imag + (lln[s-r+M1].real * lln[n+r+M1].imag + lln[s-r+M1].imag * lln[n+r+M1].real)*lam[r+M1];
}
}
}
}
/* The gateway routine. */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
int N = (int) mxGetScalar(prhs[3]);;
/* coppy array and set the output pointer to it */
plhs[0] = mxDuplicateArray(prhs[2]);
/* call the C subroutine */
myMexFunction(prhs[0], prhs[1], plhs[0], N);
return;
}
When I call this function from matlab using:
mex myMexFunction.cpp -R2018a
Lsn_=myMexFunction(lambda,ll_n,Lsn,N);
I can see that the function goes into all loops but if I assign any value to out[] matlab crashes. I cannot assign even a fixed value to out[1] so it is not index related.
What can i do to get it work?
Thanks

Réponse acceptée

James Tursa
James Tursa le 31 Mai 2018
Some problems:
1)
/* coppy array and set the output pointer to it */
plhs[0] = prhs[2];
The above line does not copy the input array to the output array. It only copies a pointer to a pointer. Furthermore, you cannot copy input prhs[] pointers to output plhs[] pointers directly. This violates the rules and can cause a MATLAB crash. Probably what you want instead is a deep copy:
plhs[0] = mxDuplicateArray(prhs[2]);
2)
out[s+M1,n+M1].real = out[s+M1,n+M1].real + etc.
The above line does not do the indexing like you think it is doing. This is not the way to index into a 2D array in C/C++. What you are actually doing in the above line is evaluating the result of a comma operator and using that as a single index. Since the result of a comma operator is the value of the 2nd expression, the above line is the equivalent of
out[n+M1].real = out[n+M1].real + etc.
You will need to manually calculate the equivalent linear index corresponding to the 2D element you are trying to update, and use that linear index instead of what you are doing.
3)
int N = prhs[3];
The above line copies an mxArray * type into an integer. This does not get the value into N. To do that you need to do this instead:
int N = (int) mxGetScalar(prhs[3]);
There are probably other errors too, but I can't read your screen shot above. Please delete the screen shot and post the error messages as text instead.
  8 commentaires
ttopal
ttopal le 1 Juin 2018
I have finally figured it. The initial array that i duplicated (zeros matrix from matlab) was not complex type, hence the crash! I was doing it so that I didnt have to write to loops to make a zeros matrix in c++. One final question is how i can make out[][] indexing work?
James Tursa
James Tursa le 4 Juin 2018
"how i can make out[][] indexing work?"
You can make the [][] indexing syntax work, sort of, but IMO it usually isn't worth the trouble and I prefer simple linear indexing instead. MATLAB data storage ordering in memory is column-based, but native C/C++ arrays are stored in memory row-based. So if you use the [][] syntax on a native C/C++ 2D array it will naturally be interpreted as [row][column]. But if you attempt to use [][] on a MATLAB mxArray 2D matrix memory block it will be interpreted as [column][row] ... i.e. basically the transpose of the C/C++ interpretation. So it can get a bit confusing to the reader.
I wrote a detailed mex example of all of this on Answers some time ago, but I can't find the post at the moment. In lieu of that, here is a short example. The code simply prints out a full double complex 2D matrix to the screen:
#include "mex.h"
#define PR(i,j) pr[(i)+M*(j)]
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mxComplexDouble *pr;
mxComplexDouble **ptr;
size_t M, N, i, j;
if( nrhs != 1 || !mxIsDouble(prhs[0]) || !mxIsComplex(prhs[0]) ||
mxIsSparse(prhs[0]) || mxGetNumberOfDimensions(prhs[0]) != 2 ) {
mexErrMsgTxt("Need one full double complex 2D input");
}
if( nlhs ) {
mexErrMsgTxt("Too many outputs");
}
pr = mxGetComplexDoubles(prhs[0]);
M = mxGetM(prhs[0]);
N = mxGetN(prhs[0]);
/* Linear Indexing */
mexPrintf("Linear Indexing\n");
for( i=0; i<M; i++ ) {
mexPrintf("Row %2d = ",i+1);
for( j=0; j<N; j++ ) {
mexPrintf("%g + %gi ,",pr[i+M*j].real,pr[i+M*j].imag);
}
mexPrintf("\n");
}
mexPrintf("\n");
/* Macro Indexing */
mexPrintf("Macro Indexing\n");
for( i=0; i<M; i++ ) {
mexPrintf("Row %2d = ",i+1);
for( j=0; j<N; j++ ) {
mexPrintf("%g + %gi ,",PR(i,j).real,PR(i,j).imag);
}
mexPrintf("\n");
}
mexPrintf("\n");
/* [][] Indexing */
mexPrintf("[][] Indexing\n");
ptr = (mxComplexDouble **) mxMalloc( N * sizeof(*ptr) ); /* Allocate the column pointer array */
/* Fill in the column pointer array */
ptr[0] = pr;
for( j=1; j<N; j++ ) {
ptr[j] = ptr[j-1] + M;
}
for( i=0; i<M; i++ ) {
mexPrintf("Row %2d = ",i+1);
for( j=0; j<N; j++ ) {
mexPrintf("%g + %gi ,",ptr[j][i].real,ptr[j][i].imag); /* Note the order of [j][i] */
}
mexPrintf("\n");
}
mexPrintf("\n");
mxFree(ptr); /* Free the column pointer array */
}
And a sample run:
>> mex indexing2D.c -R2018a
Building with 'Microsoft Visual C++ 2013 (C)'.
MEX completed successfully.
>> x = reshape(1:12,3,4) - reshape(1:12,3,4)*i
x =
1.0000 - 1.0000i 4.0000 - 4.0000i 7.0000 - 7.0000i 10.0000 -10.0000i
2.0000 - 2.0000i 5.0000 - 5.0000i 8.0000 - 8.0000i 11.0000 -11.0000i
3.0000 - 3.0000i 6.0000 - 6.0000i 9.0000 - 9.0000i 12.0000 -12.0000i
>> indexing2D(x)
Linear Indexing
Row 1 = 1 + -1i ,4 + -4i ,7 + -7i ,10 + -10i ,
Row 2 = 2 + -2i ,5 + -5i ,8 + -8i ,11 + -11i ,
Row 3 = 3 + -3i ,6 + -6i ,9 + -9i ,12 + -12i ,
Macro Indexing
Row 1 = 1 + -1i ,4 + -4i ,7 + -7i ,10 + -10i ,
Row 2 = 2 + -2i ,5 + -5i ,8 + -8i ,11 + -11i ,
Row 3 = 3 + -3i ,6 + -6i ,9 + -9i ,12 + -12i ,
[][] Indexing
Row 1 = 1 + -1i ,4 + -4i ,7 + -7i ,10 + -10i ,
Row 2 = 2 + -2i ,5 + -5i ,8 + -8i ,11 + -11i ,
Row 3 = 3 + -3i ,6 + -6i ,9 + -9i ,12 + -12i ,

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Write C Functions Callable from MATLAB (MEX Files) dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by