I have an interesting problem. Namely like that; I am trying to use std::memcpy function inside by mex function and calling that mex function inside MATLAB like that;
I2 = b_filter(I);
When I copy the whole image, it works well;
plhs[0] = mxCreateDoubleMatrix(mxGetM(plhs[0]), mxGetN(plhs[0]), mxREAL);
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) *mxGetM(plhs[0]) * mxGetN(plhs[0]));
But when I try to copy some part of image
plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) * 100 * 100);
it doesn't give right image part but gives unmeaningful pixel values.
So what is going on here?
Ha Ha! You've been caught by one of the nastiest of mex file nuances! It's got me before too. Arrays in mex functions are stored in column order not row order, so you:
You still use column-first indexing like in Matlab, though
Blog URL
Try this page too for a nice picture of the ordering.
Finally I would recommend reading this thread to get a better idea behind the difference of C and MATLAB matrix memory being column-ordered.
As explained by #macduff, MATLAB uses a column-major order to store arrays, while C arrays are row-major.
Here is a sample implementation showing how to copy part of a matrix.
matrix_slice_mex.c
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *in, *out;
mwIndex i,j;
mwSize numRows;
/* input checks */
if (nrhs != 1 || nlhs > 1) {
mexErrMsgIdAndTxt("MATLAB:nargchk", "Wrong number of arguments.");
}
if (mxGetNumberOfDimensions(prhs[0])>2 || !mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MATLAB:wrongDims", "Expecting 2D double matrix.");
}
if (mxGetM(prhs[0])<100 || mxGetN(prhs[0])<100) {
mexErrMsgIdAndTxt("MATLAB:wrongDims", "Matrix size must be >= 100x100.");
}
/* extract sub-matrix */
plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
out = mxGetPr(plhs[0]);
in = mxGetPr(prhs[0]);
numRows = mxGetM(prhs[0]);
for(j=0; j<100; j++) {
for(i=0; i<100; i++) {
*out++ = in[i + numRows*j];
}
}
}
And to test this:
x = rand(1000);
y = x(1:100,1:100);
yy = matrix_slice_mex(x);
isequal(y,yy)
You could have also used memcpy to copy each of the columns (one for-loop instead)
Related
I have a problem with MEX files in C/C++ coding.
I need to return a double complex array to Matlab but I am not able to do that and I don't find information about it. I show my code with some tries:
double complex output[nSymb];
nlhs = 1;
plhs[0] = mxCreateDoubleMatrix(nSymb,(mwSize)nlhs,mxCOMPLEX);
// 1º option
plhs[0] = output;
// 2º option
memcpy(plhs, output, nSymb * sizeof(double complex));
// 3º option
plhs = output;
Thanks you in advance.
You mentioned C++, so I've shown an example copying a std::vector<double> into an MxArray object, same can be applied to C-style arrays:
mxArray* CreateDoubleArray(const std::vector<double>& d)
{
mxArray* m = mxCreateDoubleMatrix(d.size(), 1, mxComplexity::mxReal); // mxComplexity::mxCOMPLEX
double* pm = mxGetDoubles (m); // mxGetComplexDoubles
for (size_t i=0; i<d.size(); i++)
{
pm[i] = d[i];
}
return m;
}
// ...
// Return value for the Mex:
plhs[0] = CreateDoubleArray(stdVecObj);
You can change the value_type of the vector to std::complex, and apply the changes suggested in the comments to handle complex type instead of double. mxGetComplexDoubles returns a MxDOUBLE_CLASS* documented here (it's just a struct with a real and imaginary component of type mxDouble).
I'm writing a c++ code that opens Matlab API engine. In the demo file Matlab_ROOT/extern/examples/eng_mat/engdemo.cpp, it shows how to copy a simple 1d c style array to a mxArray:
mxArray *T = NULL; double time[10] = {};
T = mxCreateDoubleMatrix( 1,10,mxREAL);
memcpy((void*)mxGetPr(T), (void*)time, sizeof(time));
I can understand this code; so a 1d mxArray object stores the elements linearly.
However, suppose I have a 2d (or more) c array and mxArray of same size:
double time[3][5];
mxArray *T;
T = mxCreateDoubleMatrix(3,5,mxREAL);
and I want to copy the elements of the c array time into mxArray T. How can I do this? I suppose if I use memcpy, it would depend on the sequence of element storage in mxArray objects. Thanks!
No matter what the dimensionality of your mxArray matlab always stores it as a continuous chunk in memory (column first order). That is, if your matrix M is 2-by-3
M = [ 11, 12, 13;
21, 22, 23 ];
In memory, Matlab stores it as
[11, 21, 12, 22, 13, 23]
(The same order you'll get if you do M(:)).
Therefore, to convert a double[3][5] to mxArray you'll have to issue several memcpy commands:
double* ptr = mxGetPr( T );
for ( int i=0; i<3; i++ )
memcpy( (void*)(ptr+i*5), (void*)time[i], 5*sizeof(double) );
One way of doing this is illustrated in another Matlab demo file matlabroot/extern/examples/refbook/arrayFillSetData.c. Things works well except that the c style array has to be in a Matlab-supported type and in linear form. Matlab stores 2d array in column major and c in row major, so care must be taken. A transpose action might be needed.
#define ROWS 2
#define COLUMNS 2
#define ELEMENTS 4
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
UINT16_T *dynamicData; /* pointer to dynamic data */
const UINT16_T data[] = {2, 3, 2, 1}; /* existing data */
mwSize index;
/* Check for proper number of arguments. */
if ( nrhs != 0 ) {
mexErrMsgIdAndTxt("MATLAB:arrayFillSetData:rhs",
"This function takes no input arguments.");
}
/* Create a local array and load data */
dynamicData = mxCalloc(ELEMENTS, sizeof(UINT16_T));
for ( index = 0; index < ELEMENTS; index++ ) {
dynamicData[index] = data[index];
}
/* Create a 0-by-0 mxArray; you will allocate the memory dynamically */
plhs[0] = mxCreateNumericMatrix(0, 0, mxUINT16_CLASS, mxREAL);
/* Point mxArray to dynamicData */
mxSetData(plhs[0], dynamicData);
mxSetM(plhs[0], ROWS);
mxSetN(plhs[0], COLUMNS);
/* Do not call mxFree(dynamicData) because plhs[0] points to dynamicData */
return;
}
I am trying to run my mex function which I've written in c++ in VS. It compiles successfully in MATLAB but returns the wrong values. I'm pretty much sure, I'm not reading the 16-by-21 input matrix gammas. Can anybody see what is wrong here?
void fun(double gammas[], int num1, int num2, int length, double a[])
{
...
}
void mexFunction(int nlhs, mxArray *plhs, int nrhs, const mxArray *prhs)
{
double *gammas, *a;
int num1, num2, length;
size_t mrows, mcols;
mrows = 4; mcols = 21;
length = 21;
plhs[0] = mxCreateDoubleMatrix((mSize)mrows, (mwSize)ncols, mxREAL);
gammas = mxGetPr(prhs[0]);
num1 = (int)*mxGetPr(prhs[1]);
num2 = (int)*mxGetPr(prhs[2]);
a = mxGetPr(plhs[0]);
fun(gammas, num1, num2, length, a);
}
I get correct "a" when I call "fun" within a "main" instead of "mex" function in VS and manually provide the input gammas. I receive wrong "a" when I call the resulted mex file in my MATLAB code.
As suspected in comments to your question issue is due to how matlab and c/c++ order array elements for linear storage as 1D array in memory. Matlab uses column-major order while C/C++ uses row-major.
I would not advice you to do permutation prior to call mex-function but rather do the permutation inside the mex function. Either as suggested by #chappjc by call to permute with mexCallMatlab or by call to mxCalcSingleSubscript which returns matlab's linear index from coordinates (whatever the number of dimensions).
Side note: Need confirmation and find back great article I read about that, but matlab uses column-major ordering because it's more appropriate for matrix multiplication (creates less page-defaults when accessing memory cache, and is thus faster). Again need confirmation ... but at least this organisation is better suited for access by columns rather than by rows ...
Edit
Btw, some simple code (C#) to obtain coordinates from maltab's zero based linear index (reverse of mxCalcSingleSubscript):
private static int[] getCoordinatesFromMatlabLinearIndex(int index, int[] arrayDims)
{
var ret = new int[count];
var count = arrayDims.Length;
for (var k = 0; k < count; k++)
{
index = Math.DivRem(index, arrayDims[k], out ret[k]);
}
return ret;
}
As an alternative to inputting a transposed matrix to address the row/column-major discrepancy that CitizenInsane pointed out, you can have the transpose handled inside the MEX file. Use a helper C++ function. You can either write a loop to copy elements, or simply call permute via mexCallMATLAB. Something like the following:
int permute2DMATtoC(mxArray*& matPermuted, const mxArray* mat)
{
mxAssert(mxGetNumberOfDimensions(mat)<=3, "Requires 2D or 3D matrix.");
mxArray *permuteRHSArgs[2];
permuteRHSArgs[0] = const_cast<mxArray*>(mat);
permuteRHSArgs[1] = mxCreateDoubleMatrix(1,3,mxREAL);
mxGetPr(permuteRHSArgs[1])[0] = 2;
mxGetPr(permuteRHSArgs[1])[1] = 1;
mxGetPr(permuteRHSArgs[1])[2] = 3; // supports 2D and 3D
return mexCallMATLAB(1, &matPermuted, 2, permuteRHSArgs, "permute");
}
Use:
mxArray *matPermuted;
permute2DMATtoC(matPermuted, prhs[0]); // matPermuted is MATLAB-managed
double *gammas = (double*)mxGetData(matPermuted);
NOTE: Since matPermuted is manage by MATLAB, you don't need to explicitly destroy it to reclaim resources, but when you are done you can do this if you want:
mxDestroyArray(matPermuted);
For RGB, it may be necessary to convert pixel order (RGB-RGB-RGB-...) to planar order (RRRR...-GGGG...-BBBB...).
I have written a mex code which sends a scalar and a matrix to C-code from matlab code. My code is supposed to return the sparse matrix after putting it in TAUCS format (page 12; also a column major format).
I am concerned that I may not be assigning LHS correctly and returning null pointer or I may not be cleaning the memory properly. Would someone please let me know if I am doing something wrong?
Part of my matlab code:
% Create system matrix (size 8448 x 3264)
smA_System = ConstructSystemMatrix();
x = 9;
y = ones(3);
% This works fine
z = mexcallingmatlab(x, y);
% This gives error
z = mexcallingmatlab(x, smA_System);
My mex code:
#include "mex.h"
#include "matrix.h" // definition of Matlab sparse matrix
#include<stdio.h>
//#include "/usr/local/lib/taucs_full/src/taucs.h"
#include "/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic/taucs.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *y, *z, x;
/* Declare variable */
mwSize mrows,ncols;
int status;
mwSize nzmax;
mwIndex *irs,*jcs,j,k;
/* Check for proper number of arguments. */
if (nrhs != 2)
mexErrMsgTxt("Two inputs required.");
if (nlhs != 1)
mexErrMsgTxt("One output required.");
/* Check to make sure the first input argument is a scalar. */
if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxGetN(prhs[0])*mxGetM(prhs[0]) != 1) {
mexErrMsgTxt("Input x must be a scalar.");
}
/* Get the scalar input x. */
x = mxGetScalar(prhs[0]);
/* Create a pointer to the input matrix y. */
y = mxGetPr(prhs[1]);
/* Check data type dimensions of the matrix input y. */
if (!(mxIsDouble(prhs[1]))){
mexErrMsgIdAndTxt( "MATLAB:DKU", "Input argument must be of type double.");
}
if (mxGetNumberOfDimensions(prhs[1]) != 2){
mexErrMsgIdAndTxt( "MATLAB:DKU", "Input argument must be two dimensional\n");
}
/* Get the size and pointers to input data */
mrows =mxGetM(prhs[1]);
ncols = mxGetN(prhs[1]);
// Verify the matrix y is infact sparse
if (!(mxIsSparse(prhs[1]))){
mexErrMsgIdAndTxt( "MATLAB: DKU", "Input matrix is not sparse\n");
}else{
//Work with irs and jcs directly instead of row-column pairs that are less compact.
sr = mxGetPr(prhs[1]);
jcs = mxGetJc(prhs[1]);
irs = mxGetIr(prhs[1]);
}
// Now converting sparse matrix to TAUCS format
taucs_ccs_matrix *A;
A = (taucs_ccs_matrix*)malloc(sizeof(taucs_ccs_matrix));
A->n = ncols;
A->m = mrows;
A->flags = TAUCS_DOUBLE;
// Allocating spaces
int nnz = jcs[ncols];
A->colptr = (int*)mxMalloc(sizeof(int)*(A->n+1));
A->rowind = (int*)mxMalloc(sizeof(int)*nnz);
A->values.d = (double*)mxMalloc(sizeof(taucs_double)*nnz);
int icolOffset = 0; // Matlab "SPARSE" indices start with 0 vs 0 based in C
A->colptr = jcs-icolOffset;
A->rowind = irs-icolOffset;
A->values.d = sr;
/* Create a C pointer to a copy of the output matrix. */
memcpy(mxGetPr(plhs[0]), &A, sizeof(A));
//Freeing spaces
mxFree(A->colptr);
mxFree(A->rowind);
mxFree(A->values.d);
}
Also, can someone confirm that what's basically written as "colptr" is not a real pointer; but is just like a pointer conceptually ?
I would like to use Matlab's delaunayTriangulation class to construct the triangulation of a set of points in 3D, P [nx3 matrix], within a mex function.
In Matlab,
DT = delaunayTriangulation(P)
computes the triangulation with 'Points' & 'ConnectivityList' as the class properties of DT.
How do I perform the same operation within a mex file?
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
....
int n;
int elements = n*3;
double* P_ptr; /*contains 3D coordinates*/
P_ptr = mxMalloc(elements * sizeof(double));
/* fill up P_ptr with coordinates */
mxArray *DT, *P;
mxSetPr(P,P_ptr); /* Set P_ptr to mxArray P */
mxSetM(P, n);
mxSetN(P, 3);
mexCallMATLAB(1, &DT, 1, &P, "delaunayTriangulation");
....
}
Is it the right way to go? Also, if the code above is right, how do I access the class properties(Points, ConnectivityList) from output mxArray *DT?
Thanks
Edit: Changed DT to &DT for correctness in the code above. Also, based on Sam's solution, I was able to access the property (e.g. "ConnectivityList") by the following code:
mxArray* variable_name = mxGetProperty(DT,0,"ConnectivityList");
You should be able to use mxGetProperty to access the properties of an object in an mxArray.