Use matrix c\c++ API with row-based indexing

Hi all, in my project I perform some calculations in c++, and then I am using Matrix API (mxCreateNumericArray) to save my 2D array into .mat file. In c++ I work with native row-based indexing, however Matlab functions assume column-based order. Is there an option to quickly fix this? I can convert row-based to column based, but don't want to do this (for greater performance). Btw, my array is not symmetric. Here is a piece of c++ code:
const mwSize dims[] = { M1, M2 };
mxArray *pa1 = mxCreateNumericArray(2, dims, mxSINGLE_CLASS, mxREAL);
memcpy((void *)(mxGetPr(pa1)), (void *)iu_cpu, M1*M2*sizeof(float));
matPutVariable(pmat, "LocalDouble", pa1);
mxDestroyArray(pa1);
So, iu_cpu is 1D array representing 2D matrix in row-based order. And matlab 2D array pa1 is obtained from iu_cpu assuming column-based order.
Here is simple example: Imagine I have matrix
a={1 2 3
4 5 6
7 8 9
10 11 12}
Then, iu_cpu={1,2,3,4,5,6,7,8,9,10,11,12}. However array pa1 will be obtained from iu_cpu assuming column-major order: pa1={1,4,7,10,2,5,8,11,3,6,9,12}
Update: Following the advice of James Tursa, I tried to use mexCallMATLAB. For some reason, Unhandled expression:access violation error appears when I am tring to call this function. Here is full code:
#include "mat.h"
#include "iostream"
#include "mex.h"
int main(){
float data[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
MATFile *pmat = matOpen("mattest.mat", "w");
const mwSize dims[] = { 3, 3 };
mxArray *pa1 = mxCreateNumericArray(2, dims, mxSINGLE_CLASS, mxREAL);
mxArray *pa1T;
memcpy((void *)(mxGetPr(pa1)), (void *)data, 3 * 3 * sizeof(float));
mexCallMATLAB(0, NULL, 1, &pa1, "disp");
mexCallMATLAB(1, &pa1T, 1, &pa1, "transpose");
matPutVariable(pmat, "LocalDouble", pa1T);
mxDestroyArray(pa1);
mxDestroyArray(pa1T);
}
Even simple mexCallMATLAB(0, NULL, 1, &pa1, "disp"); causes this error. May be I didn't add something to my project? Even this sample code http://www.mathworks.com/help/matlab/apiref/rmvd_matlablink__4f95060e6fdb200c8b9414502f277cc0.html doesn't work(unresolved external symbol)
Update 2: Full output:
1>------ Build started: Project: wrtie_mat, Configuration: Debug x64 ------
1> Source.cpp
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol main referenced in function __tmainCRTStartup
1>C:\programs\misha\cuda\Projects\test projects\wrtie_mat\x64\Debug\wrtie_mat.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
When I tried to compile in matlab (mex Source.cpp), there was also error:
Unable to complete successfully.

 채택된 답변

James Tursa
James Tursa 2015년 2월 14일

1 개 추천

You could transpose it after loading the mat file. Or you could call MATLAB to transpose it for you prior to saving the variable to a mat file. E.g.,
mxArray *pa1T;
mexCallMATLAB(1, &pa1T, 1, &pa1, "transpose");
matPutVariable(pmat, "LocalDouble", pa1T);
mxDestroyArray(pa1T);
mxDestroyArray(pa1);

댓글 수: 15

Mikhail
Mikhail 2015년 2월 16일
편집: Mikhail 2015년 2월 16일
Access violation error - something wrong with memory.
James Tursa
James Tursa 2015년 2월 16일
편집: James Tursa 2015년 2월 16일
Please re-post your complete code as you currently have it. You still need to create the pa1 variable ... what I posted was just steps to do in place of the matPutVariable(pmat,"LocalDouble",pa1) line.
Mikhail
Mikhail 2015년 2월 17일
I did it in UPDATE. Thanks for helping
Mikhail
Mikhail 2015년 2월 17일
Btw, I feel like I didn't "install" everything. All I did in order this stuff to work in VS2013 is added "matlabroot/extern/include" folder into additional search and added all libs I found in "matlabroot/extern/libs"
James Tursa
James Tursa 2015년 2월 17일
편집: James Tursa 2015년 2월 17일
This works fine for me as a mex routine (not a program or an Engine app). I added the include for string.h to get the prototype for memcpy. (I suppose I should add that I think it strange that a single class variable is named "LocalDouble")
#include "mat.h"
#include "iostream"
#include "mex.h"
#include <string.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
float data[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
MATFile *pmat = matOpen("mattest.mat", "w");
const mwSize dims[] = { 3, 3 };
mxArray *pa1 = mxCreateNumericArray(2, dims, mxSINGLE_CLASS, mxREAL);
mxArray *pa1T;
memcpy((void *)(mxGetPr(pa1)), (void *)data, 3 * 3 * sizeof(float));
mexCallMATLAB(0, NULL, 1, &pa1, "disp");
mexCallMATLAB(1, &pa1T, 1, &pa1, "transpose");
mexCallMATLAB(0, NULL, 1, &pa1T, "disp");
matPutVariable(pmat, "LocalDouble", pa1T);
mxDestroyArray(pa1);
mxDestroyArray(pa1T);
matClose(pmat);
}
>> mex transp.cpp
Building with 'Microsoft Visual C++ 2013 Professional'.
MEX completed successfully.
>> transp
1 4 7
2 5 8
3 6 9
1 2 3
4 5 6
7 8 9
>> load mattest
>> LocalDouble
LocalDouble =
1 2 3
4 5 6
7 8 9
>> class(LocalDouble)
ans =
single
HOWEVER, this is all good for a mex routine, but NOT for a program as you have set up. So mexCallMATLAB cannot be used in this case. You have three options as I see it:
1) Open up a MATLAB Engine and then call the Engine to do the transpose (e.g., manually or via the engCallMATLAB routine you can find in the FEX).
2) Manually transpose the data yourself inside your C++ routine before saving it to the mat file.
3) Manually transpose the variable after loading it into MATLAB.
I think (1) is overkill for what you are doing, and I would just go with (2) myself. The code for transposing isn't that difficult, but let me know if you need help with it.
Mikhail
Mikhail 2015년 2월 17일
Doesn't work! unresolved external symbol. This is strange - I added all libs,that were in "matlabroot/extern/libs/win64/microsoft"
James Tursa
James Tursa 2015년 2월 17일
What doesn't work? Building the mex routine? Or building your project?
Mikhail
Mikhail 2015년 2월 17일
Building my project
Mikhail
Mikhail 2015년 2월 17일
See Update 2.
James Tursa
James Tursa 2015년 2월 17일
You can't use mexCallMATLAB in your project. You need to replace those lines with other code that you write.
Mikhail
Mikhail 2015년 2월 17일
Now I am confused. Why then you suggested it? Which code should I use?
Mikhail
Mikhail 2015년 2월 17일
AAAAAAAAAAAAAAAAAAAAAAAAAA got it. I can use this function only when I compile files in matlab. Got it! thanks
Mikhail
Mikhail 2015년 2월 17일
I naively thought, that I can use any matlab function in c++ code and compile it with c++ compiler.
James Tursa
James Tursa 2015년 2월 17일
편집: James Tursa 2015년 2월 17일
I originally suggested mexCallMATLAB because you did not post your entire code. You only posted a code snippet that did not tell me you were building a C++ program rather than a mex routine. Once you posted code showing the int main(){, I knew you were compiling a program and not a mex routine, and have tried to steer you away from mexCallMATLAB ever since. Sorry for the confusion.
You cannot use ANY of the mex-only routines from the API in your program, and that includes mexCallMATLAB. So again I would go back to my advice a few posts earlier. (1) Open an Engine (not my choice), (2) manually code up the transpose yourself in C++ prior to saving it to the mat file (my choice), or (3) transpose it after reading the variable from the mat file.
Again, I apologize for originally suggesting mexCallMATLAB, but I did not know at the time you were compiling a program instead of a mex routine.
If you opt for (2) and need help let me know.
Mikhail
Mikhail 2015년 2월 17일
Thanks again. I don't need further help, I think, I will transpose it in matlab (since it is only " ' " command).

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Write C Functions Callable from MATLAB (MEX Files)에 대해 자세히 알아보기

제품

태그

질문:

2015년 2월 13일

댓글:

2015년 2월 17일

Community Treasure Hunt

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

Start Hunting!

Translated by