Mex function out plhs[0] is all zeros
8 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Aparna Singh
le 15 Avr 2020
Commenté : Aparna Singh
le 17 Avr 2020
Hello, I am fairly new to programming mex function and new to C++. I am trying to write a mex function that accepts data from matlab and processes it and then outputs the processed data. I have copied pasted my c++ code. my plhs code is giving me all 0s and i dont know why that is happening. the result data (odata) looks correct (i know because I used mexprintf to print it out and compare it to the h_raw data which is the input.
#include <iostream>
#include "mex.h"
short* matData(short *h_raw, int nrows,int ncols) {
int dim_x = nrows;
int dim_y = ncols;
int total_val = dim_x * dim_y;
short* odata;
odata = new short[total_val];
for (int i = 0; i < total_val; i++) {
int idx = i;
odata[idx] = h_raw[i];
}
//short odata = h_raw;
return odata;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
short *h_raw = (short *)mxGetData(prhs[0]);
int nrows = 1024;
int ncols = 128;
int nframes = 1;
int ndim = 3;
const mwSize dims[] = { nrows, ncols, nframes };
plhs[0] = mxCreateNumericArray(ndim, dims, mxUINT16_CLASS, mxREAL);
short* res = (short *)mxGetData(plhs[0]);
short *result = matData( h_raw, nrows, ncols);
res = result;
return;
//plhs[0] = *result;
//short t1 = *&result[0];
//mwSize NElem = mxGetNumberOfElements(prhs[0]);
//int size = sizeof(result) / sizeof(result[0]);
//mexPrintf("now h raw %d \n", h_raw[100]);
//mexPrintf("%d \n", h_raw[10]);
//plhs[0] = result;
}
0 commentaires
Réponse acceptée
James Tursa
le 15 Avr 2020
There are three problems with your code.
1) Assigning the value of a pointer to another pointer does not attach the pointer to the mxArray. I.e., this line
res = result;
simply overwrites the value currently in res with the value currently in result. It does not get this value attached to plhs[0].
2) Even if you did try to attach the pointer properly to the mxArray, it wouldn't work because you can't attach native C/C++ memory (local from stack or allocated from heap with new, malloc, calloc, etc.) to an mxArray. It would either generate an error or bomb MATLAB. I.e., the proper way to attach a pointer to an mxArray is with mxSetData( ) and friends. However, in your case even this wouldn't work:
mxSetData( plhs[0], result ); // this will generate an error or bomb MATLAB
You can only attach data memory to an mxArray if it originally came from a MATLAB API function, e.g. from mxMalloc( ) and friends.
3) Even if you allocated the memory properly and got it attached properly, you will leak memory and have a mismatch in the size of the memory and the dimensions of the variable if nframes is ever anything greater than 1. You specified the dimensions as (nrows X ncols X nframes), but inside your routine you only allocate memory for (nrows X ncols) elements. Pass this back to MATLAB and the first time you try to access an element beyond the 1st frame you will access invalid memory and bomb MATLAB.
The fix for all of this is to simply pass the data pointer from the plhs[0] variable into your routine. E.g.,
#include <iostream>
#include "mex.h"
void matData(short *odata, short *h_raw, int nrows, int ncols) {
int dim_x = nrows;
int dim_y = ncols;
int total_val = dim_x * dim_y;
for (int i = 0; i < total_val; i++) {
int idx = i;
odata[idx] = h_raw[i];
}
return;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
if( nrhs == 0 || !mxIsInt16(prhs[0]) ) {
mexErrMsgTxt("Input must be int16");
}
short *h_raw = (short *)mxGetData(prhs[0]);
int nrows = 1024;
int ncols = 128;
if( mxGetNumberOfElements(prhs[0]) < nrows * ncols ) {
mexErrMsgTxt("Not enough elements");
}
int nframes = 1;
int ndim = 3;
const mwSize dims[] = { nrows, ncols, nframes };
plhs[0] = mxCreateNumericArray(ndim, dims, mxUINT16_CLASS, mxREAL);
short* res = (short *)mxGetData(plhs[0]);
matData(res, h_raw, nrows, ncols);
return;
}
4 commentaires
James Tursa
le 17 Avr 2020
A C++ vector is an OOP container object, with other stuff in it besides just the data. And it has its own memory management stuff in the background. You can't take a data pointer from an mxArray and expect it to behave like an OOP object. Just stick with the pointer:
short *new_array2 = (short *) mxGetData(plhs[1]);
Also, the only plhs[ ] spot guaranteed to exist is plhs[0]. The other spots don't physically exist unless the user requests them by asking for more outputs. That is, this line is always OK:
plhs[0] = mxCreateNumericArray(ndim, dims, mxINT16_CLASS, mxREAL);
but these lines might bomb MATLAB (accessing invalid memory) unless the user requests the outputs:
plhs[1]= mxCreateNumericArray(ndim3, dims, mxINT16_CLASS, mxREAL);
plhs[2] = mxCreateNumericArray(ndim2, dims_n, mxINT16_CLASS, mxREAL);
plhs[3] = mxCreateNumericArray(ndim2, dims_n3, mxINT16_CLASS, mxREAL);
plhs[4] = mxCreateNumericArray(ndim2, dims_n4, mxINT16_CLASS, mxREAL);
You should check that nlhs >= 5 before executing these lines.
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur C Shared Library Integration 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!