How to pass as input of a mex function an integer value? - c++

I am trying to pass as argument of a mexfunction, an integer representing the number of columns for mxCreateDoubleMatrix. This integer is not supposed to be used anywhere else than in the main mexFunction.
Somehow, this doesn't seem to work.
// mex function for calling c++ code .
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
char *input_buf;
size_t buflen;
double ncols;
double *result_final;
double *result_second;
/* get the length of the input string */
buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;
/* copy the string data from prhs[0] into a C string input_ buf. */
input_buf = mxArrayToString(prhs[0]);
/* copy the int from prhs[0] to decide on length of the results. */
ncols = (int) (size_t) mxGetPr(prhs[1]);
plhs[0] = mxCreateDoubleMatrix(1, ncols, mxREAL);
plhs[1] = mxCreateDoubleMatrix(1, ncols, mxREAL);
result_final = mxGetPr(plhs[0]);
result_second = mxGetPr(plhs[1]);
/* Do the actual computations in a subroutine */
subroutine(input_buf, buflen, result_final, result_second);
}
If I take out the ncols line, all the rest works as expected. I did not include ncols as input to subroutine because it is not actually used there but only in the main, to define the size of the output array.
I am expected to have a matrix of 1x100 for the output array if I call myfun('examplefile.txt',100) instead the matrix that is shown at the end of the call has an infinite/very long number of columns.
Someone can help with this?

You are converting the pointer to the value into a size_t and then an int. But its a pointer, an adress in RAM of the location of the value, not the value itself.
ncols = (int) (size_t) mxGetPr(prhs[1]); %mex Get Pointer!!
Get the value instead.
ncols = (int)(mxGetScalar(prhs[1]));

Related

copy multi-dimension C array to Matlab mxArray type

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;
}

Mex : How to properly assign a sparse matrix to LHS (output) and how to properly clean memory

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 ?

Using Matlab's inbuilt class 'delaunayTriangulation' in mex

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.

memcpy function calling inside mex

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)

Import 3D array from MAT-file using C++

I would like to know if there is a way to know the 'z' dimension of a 3D array when reading data from a 'MAT-file' using the MATLAB API. I've implemented a function to load the data from file as follows:
double* importMATFile(const char* i_file)
{
MATFile *pMF;
// open MAT-file
pMF = matOpen(i_file, "r");
// check for file errors
// Matlab Array Data
mxArray *mArrayData;
// Matlab Variable Name
const char* mVarName = NULL;
// read data from file
mArrayData = matGetNextVariable(pMF, &mVarName);
// pointer to mxArray data
double *dataPtr;
dataPtr = (double*) mxGetPr(mArrayData);
// NOTE MATLAB work in COLUMN-MAJOR order
// dimension of the array : rows
int32_t NROWS = mxGetM(mArrayData);
// Right now the z dimension must be known a priori
int32_t NDEPTH = 32
// dimension of the array : cols
int32_t NCOLS = mxGetN(mArrayData) / NDEPTH;
return dataPtr;
}
I'm stuck when getting the DEPTH value, in order to know the number of columns. I've have noticed that the result of the function mxGetNumberOfDimensions(mArrayData) is 3, so, the API knows there are three dimensions.
I believe what you want is mxGetDimensions. It will return the size of each of the dimensions. This should work for any number of dimensions, not just 3.