using matlab engine from c++: How to convert a int** into mxArray*

1 回表示 (過去 30 日間)
Meytal
Meytal 2011 年 8 月 29 日
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.

採用された回答

James Tursa
James Tursa 2011 年 8 月 29 日
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.
  1 件のコメント
Meytal
Meytal 2011 年 8 月 29 日
Hi James,
I just wanted to thank you for all your help. I finally succeeded.
thank you again.

サインインしてコメントする。

その他の回答 (2 件)

Pierre
Pierre 2011 年 8 月 29 日
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.
  1 件のコメント
Meytal
Meytal 2011 年 8 月 29 日
hi,
1. yes, I know about the difference, but my matrixes are square, so it doesn't matter.
2. I don't think this is what making all the trouble, but i'll check it.
thank you.

サインインしてコメントする。


Meytal
Meytal 2011 年 8 月 29 日
I tried what pierre suggested, and the convertion still does not work.
I get something like this: 1 2.10535e-314 0 0 0 0 4 1 0 0 4.21457e-302 0 0 0 0 0 0 1 0 2.122e-314 0 0 0 0 0 0 1 4.24399e-314 0 0 0 0 1 -7.84591e+298 0 0 0 0 0 0 0 0 0 1.27625e-303 0 0 0 0 0 0 1 1.66952e-308 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7.84591e+298 0 0 0 0 0 0 0 -7. 84591e+298 0 0 0 0 0 0 2.10535e-314 0 0 0 0 0 0 0 0 4.24396e-302 0 1 0 0 1 0 1 4.2066e-302 0 0 0 0 0 0 0 1 2.122e-314 0 0 0 0 0 0 0 0 0 2.10535e-314 0 0 0 0 0 0 4.2286e-302 0 0 0 1 0 0 1.27629e-303 4 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -7.84591e+298 0 0 0 0 0 0 0 0 0 1.66944e-308 0 0 0 0 0 0 2.1 0535e-314 0 0 0 0 1 0 4.23599e-302 0 0 0 0 0 1 0 0 2.122e-314 0 0 0 0 1 0
instead of this: 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Does anyone else have an idea?
  4 件のコメント
James Tursa
James Tursa 2011 年 8 月 29 日
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?
Meytal
Meytal 2011 年 8 月 29 日
the double** value points to the matrix I want to convert. It's supposed to be contiguous in memory, it is allocated this way:
opSet = new double*[columns];
for (p=0; p<columns ; p++)
opSet[p] = new double[rows];

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeCreating and Concatenating Matrices についてさらに検索

タグ

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by