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 ExchangeWrite 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