using matlab engine from c++: How to convert a int** into mxArray*
2 views (last 30 days)
Show older comments
Hi,
I am opening matlab engine from c++, and I want to find the inverse matrix of a matrix. I have tried to convert the int** matrix into mxArray* in different ways, without success:
S = mxCreateDoubleMatrix(v->getCols(), v->getRows(), mxREAL);
memcpy(mxGetPr(S), v->getOpSet(), sizeof(v->getOpSet()));
or:
S = mxCreateDoubleMatrix(v->getCols(), v->getRows(), mxREAL);
mxSetPr(S,(double*)v->getOpSet());
double *acc =mxGetPr(S);
for(p=0;p<mxGetM(S); p++){
for(p1=0 ; p1<mxGetN(S) ; p1++){
cout<< acc[mxGetM(S)*p1+p];
}
}
cout<<endl;
On my first try, the first 2 elements are exponential and weird, and the rest of the matrix is 0.
on my second try, all of the elements are weird, and I get segmentation fault.
have someone have some experience with this and knows how to make the convertion?
another problem I have is that I can't get the result in an array, only as string. meaning,how can I get 'x' as a double array (not mxArray) after this:
buffer[BUFSIZE] = '\0';
engOutputBuffer(ep, buffer, BUFSIZE);
engEvalString(ep, "x = mldivide(S,T)");
(after this code, buffer contains the right result, but if I do:
D=engGetVariable(ep, "x");
D doesn't contain the right result.
is there a way to do this right?
thank you.
0 Comments
Accepted Answer
James Tursa
on 29 Aug 2011
Repeating your comment above for how you allocate opSet:
opSet = new double*[columns];
for (p=0; p<columns ; p++)
opSet[p] = new double[rows];
Since you allocate it this way, it is NOT guaranteed to be contiguous in memory as you claim. What you have done is first allocate an array of row pointers, and then each row pointer gets allocated a row of memory and those rows are NOT required to be next to each other in memory. They might happen to be for a particular run, but they might not be for another run. This is not a good way to allocate a matrix. What you should be doing is allocate the entire matrix as one contiguous block, and then if you want row pointers you can set them to point as desired. e.g., something like this:
opSet = new double*[columns];
opSet[0] = new double[rows*columns];
for (p=1; p<columns ; p++)
opSet[p] = opSet[p-1] + rows;
That way you are guaranteed that the matrix is contiguous in memory and you can reliably use memcpy etc to copy the entire contents at once by just using the address in opSet[0]. Also, it is easier to clean up since you only have to delete opSet[0] and opSet (i.e., you don't need a for loop to delete opSet[1] through opSet[columns-1] since they were not separately allocated).
On the memcpy side, be sure you are using the v->opSet()[0] address, not just v->opSet() as you show above. The first is the address of the double data, while the second is the address of the row pointer array (not what you want to copy).
For the number of bytes to copy, you also incorrectly use sizeof(v->getOpSet()), which will give you the size of a pointer (typically 4 or 8 depending on your system). You should be using something like v->getCols() * v->getRows() instead.
More Answers (2)
Pierre
on 29 Aug 2011
I didn't really get your posted code as it requires some guessing, but let me point out a few things:
1. While you might be used to row-major order from C++ code/libraries, MATLAB uses column-major order. This requires you to manually reorganize data when passing from one representation to the other one. (And, most likely it should be mxCreateDoubleMatrix(v->get Rows(), v->get Cols(), mxREAL);
2. To be honest, I didn't check that explicitely, but after years of excessive C++ coding, I'd personally never expect the canonical casting of an array's content to work: Casting an int to double, is something different than casting an int* to a double* !!!
int i = 1234;
double d = (double)i; // d=1234.0
but
int* i_ptr = new int;
*i_ptr = 1234;
double* d_ptr = (double*) i_ptr; // (*d_ptr) = ???
(*d_ptr) will read out the integer represenation of 1234 as if it was stored as a double in memory.
Meytal
on 29 Aug 2011
4 Comments
James Tursa
on 29 Aug 2011
What does the (double **) value that is returned by getOpSet point to? E.g., if I do this: double **x = v->getOpSet(), then what does x point to? What does *x point to? Is your array data contiguous in memory, and if so how would I get the starting address of the data from x?
See Also
Categories
Find more on Creating and Concatenating Matrices in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!