Reputation: 409
I am trying to call a function in C++ in Matlab, I thought I have written my functions properly. The function I want to call, looks like this, it has 8 arguments as input.
void LimitedPrice(double &dMarketPosition, double** dmatLimitPrice,
char* FileID, double* dvecOpen, double* dvecClose,
double** dmatTempData, int tick, double dMaxBarBack)
{Bla, Bla, Bla}
I want to get 2 values after running this function. Which stored in dMarketPosition, and dmatLimitPrice since they are pointers.
In this function, I have to use some ** (double pointers) to represent my Matrix.
After running this function, dMarketPosition, dmatLimitPrice will store what I want, since they are pointers. I have tested my function and I believed my function are written properly.
Now I am ready to write my mexFunction(). My mex function somehow looks like this
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs,const mxArray *prhs[])
{
if(nrhs!=8){
mexErrMsgIdAndTxt("LimitPrice: ","I want to 8 inputs");
}
// I want two output
if(nlhs!=2) {
mexErrMsgIdAndTxt("LimitPrice: ","I want to 2 outputs");
}
//The first input is a scalar
double dmarketposition;
dmarketposition = mxGetScalar(prhs[0]);
//The second input is a 2-dimensional Matrix
double **dmatlimitprice;
*dmatlimitprice = mxGetPr(prhs[1]);
/*****Assuming I have checked other inputs here properly*****/
// I want to define my outputs
// Create 1*1 matrix as output, which is the double value I want
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
//The second output is a two dimensional matrix
plhs[1] = mxCreateDoubleMatrix(2,(mwSize)4,mxREAL);
dmarketposition = mxGetScalar(plhs[0]);
*dmatlimitprice = mxGetPr(plhs[0]);
// Call the function
LimitedPrice(dmarketposition, dmatlimitprice, fileid,
dvecopen, dvecclose, dmattempdata, tick, dmaxbarback);
}
The above function does not seem to work... It seems that in mexFunction(), We would better only pass one-dimensional array, which is double *a like thing.
My key issue is "How can we deal with 2-dimensional array, which is a matrix" in mexFunction().
Upvotes: 1
Views: 1646
Reputation: 30579
The only thing that makes an array 2D (or any size other than 1D) is the shape of the array as stored in the mxArray
structure. All the data is contiguous. The stride, or step in bytes between columns, of a 2D array in MATLAB (and mxArray
s) is always number_of_rows * element_size
. For a column-major storage system, that's a way of saying that a contiguous data buffer is used to store all arrays.
Take the basic functions for reading from a mxArray
:
double* mxGetPr(const mxArray*); // get pointer to start of double buffer
void* mxGetData(const mxArray*); // get pointer to start of any data-type buffer
size_t mxGetM(const mxArray*); // get number of rows
size_t mxGetN(const mxArray*); // get number of columns
There is no function like OpenCV's T* ptr<T>(int i)
to get a pointer to specified row (or column in MATLAB's case). To get an element, you just have to access location irow + icol*numRows
. This is why it is common to have a sub2ind
-like function in C/C++:
inline mwSize sub2ind(mwSize irow, mwSize icol, mwSize numRows) {
return irow + icol*numRows; }
That was generic advice, nothing specific to your code. I'm hesitant to to make specific suggestions since semantics of LimitedPrice()
is not clear. The syntax is clear -- it needs a pointer to a pointer -- but often a **
is used to return a new pointer (internally allocated result) rather than to manage a 2D array. If it's 2D data then usually there will be two integral types with it to specify dimensions, but I don't see that.
For the reasons above it's hard to provide more specific help, but here here is a big issue to address:
double **dmatlimitprice;
*dmatlimitprice = mxGetPr(prhs[1]); // dereferencing uninitialized pointer, ERROR
You could make a double**
that acts as an index into the columns of the input matrix (if that is what you actually need!). For example:
size_t numCols = mxGetN(prhs[1]);
double *dlimitBuffer = mxGetPr(prhs[1]);
// Simulate a 2D array:
std::vector<double*> dlimitvec(numCols);
double **dmatlimitprice = &dlimitvec[0]; // or = new double*[numCols]; if you delete[]
for (size_t i=0; i < numCols; ++i)
datalimitprice[i] = dlimitBuffer + i*numRows;
That's assuming you need a double**
where each double*
points to the individual columns of some matrix, which is likely not correct, so treat this as an example. You may need to transpose the matrix too.
Also, you make the invalid assignment to *dmatlimitprice
twice so it's hard to tell whether you want this as the input or output array.
Upvotes: 1
Reputation: 114786
In memory, Matlab stores all mxArray
s as one chunk of contiguous memory column by column. In that respect, there is no difference beteween a 1D vector and N-D array, they are all stored as a single chunk of memory.
Consider, for example, the following chunk in memory: { 1, 2, 3, 4, 5, 6, 7, 8 }
It can be treated as a 1-by-8, 8-by-1, 2-by-4, 4-by-2 or even 2-by-2-by-2 array. Changing the shape
(reshape
-ing) of the array does not require any change to the actual memory where the data is stored, only to the "header" of the mxArray
.
What you can do is allocate a 2D matrix internally, call LimitedPrice
and then copy the result into the output mxArray
converting it from the internal double**
representation to double*
mxArray
representation.
A side note, in your example code you assign dmarketposition
and dmatlimitprice
twice: once from the first and second inputs and once from the newly allocated outputs - the second assignment simply overrides the first and it seems like your function LimitedPrice
will not get the information stored in the mexFunction
inputs.
Upvotes: 2