You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
How do I convert to Mex from Cpp using Xcode ver 10
2 views (last 30 days)
Show older comments
Stelios Fanourakis
on 18 Jun 2019
Commented: Walter Roberson
on 23 Jun 2019
For Mac Users, I need that info. Thanks
14 Comments
Geoff Hayes
on 18 Jun 2019
Stelios - what do you want to convert from C++ to Mex? A single file/program? Several files? Please provide some context.
Geoff Hayes
on 18 Jun 2019
This question seems identical to your last one: https://www.mathworks.com/matlabcentral/answers/467491-cpp-to-mex-conversion.
Stelios Fanourakis
on 18 Jun 2019
It's a cpp program that I need to run it in Matlab. I need to convert it to Mex. This is the code I need to run in Matlab.
#include "mex.h"
#include "string.h"
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs!=5)
mexErrMsgTxt("Wrong number of inputs");
if (nlhs!=1)
mexErrMsgTxt("Wrong number of outputs");
//---------------------- inputs -----------------------//
double *Bness;
double F0,F1,Bth,JumpConst;
const int *DimsBness;
DimsBness = mxGetDimensions(prhs[0]);
int bH = DimsBness[0];
int bW = DimsBness[1];
Bness = (double *)mxGetData(prhs[0]);
double *pF0,*pF1,*pBth,*pJumpConst;
pF0 = (double *)mxGetData(prhs[1]);
pF1 = (double *)mxGetData(prhs[2]);
pBth = (double *)mxGetData(prhs[3]);
pJumpConst = (double *)mxGetData(prhs[4]);
F0 = *pF0; F1 = *pF1; Bth = *pBth; JumpConst = *pJumpConst;
//---------------------- outputs ----------------------//
plhs[0] = mxCreateNumericArray(2,DimsBness,mxDOUBLE_CLASS,mxREAL);
double *imSeg = (double *)mxGetData(plhs[0]);
memset(imSeg, 0, bH*bW*sizeof(double));
//===================================================================//
double *CostF = (double *)mxCalloc(bH*bW, sizeof(double));
for (int i=0; i<bH*bW; i++) CostF[i] = 1000; // The total cost for each point
double *mini = (double *)mxCalloc(bH*bW, sizeof(double));
for (int i=0; i<bH*bW; i++) mini[i] = 1; // The index of minimum cost path from each point
double *diffF = (double *)mxCalloc(bH*bW, sizeof(double));
for (int i=0; i<bH*bW; i++) diffF[i] = JumpConst; //The slop of path at each point (for smoothness)
// The last row is used as "no bone" pass.
for (int i = 0; i<bW; i++) Bness[bH-1+bH*i] = Bth; //use a threshold for no bone
double minCF;
double Cdiff, Econt, Esmth, Etotal, CF, tmp;
double Ecnct = -0.01;
for (int ww = 1; ww<bW; ww++) {
for (int hh = 0; hh<(bH-1); hh++) {
if (Bness[hh+bH*ww]) {
// Go through the CostF(i-1,:) and find min path from there to current state
minCF = 100000;
for (int k=0; k<(bH-1); k++) {
Cdiff = (k-hh)/(double)(bH); // Current Difference (bH is just for normalization)
Econt = Cdiff*Cdiff + 1/(double)(bH*bH); // Energy of Continuity
tmp = Cdiff-diffF[k+ bH*(ww-1)];
Esmth = tmp*tmp; // Energy of Smoothness
Etotal = F0*Econt + F1*Esmth + Ecnct;
CF = CostF[k+ bH*(ww-1)] + Etotal;
if (CF<minCF) {
minCF = CF;
mini[hh+bH*ww] = k;
}
}
// From No Bone To Bone Find the cost for no bone (bH-1)
// Smoothness is found differently
// second term: a constant smoothness cost for being in no bone zone
int kk = bH-1;
Etotal = JumpConst; //(F0+F1) * (hh~=kk) * Bth;
CF = CostF[kk+bH*(ww-1)] + Etotal;
if (CF<minCF) {
minCF = CF;
mini[hh+bH*ww] = kk;
diffF[hh+bH*ww] = 0;
} else
diffF[hh+bH*ww] = (mini[hh+bH*ww]-hh)/(double)(bH);
CostF[hh+bH*ww] = (1-Bness[hh+bH*ww]) + minCF;
} else { // (!Bness[hh+bH*ww])
mini[hh+bH*ww] = bH; // go to no bone area
CostF[hh+bH*ww] = 1000 + CostF[hh+bH*(ww-1)]; // very high cost
}
}
///////// From Bone To No Bone /////////
int hhh = bH-1;
minCF = 100000;
for (int k=0; k<bH; k++) {
// add jump cost if moving from bone to no bone and add average
// smoothing factors if staying in no bone
Etotal = JumpConst*(k!=hhh) + (F0+F1) * (k==hhh) /(double)(bH*bH);
CF = CostF[k + bH*(ww-1)] + Etotal;
if (CF<minCF) {
minCF = CF;
mini[hhh+bH*ww] = k;
}
}
CostF[hhh+bH*ww] = (1-Bness[hhh+bH*ww]) + minCF;
diffF[hhh+bH*ww] = 0;
}
///////////////////////////////
double *indSeg = (double *)mxCalloc(bW, sizeof(double)); //The slop of path at each point (for smoothness)
memset(indSeg, 0, bW*sizeof(double));
/*// find the minimum cost function for the last column
double minCost = 100000;
for (int i=0; i<bH; i++) {
if (minCost>CostF[i+bH*(bW-1)]) {
indSeg[bW-1] = i;
minCost=CostF[i+bH*(bW-1)];
}
}*/
indSeg[bW-1] = bH-1;
// memoization
for (int i=bW-2; i>=0; i--) {
indSeg[i] = mini[ (int)(indSeg[i+1] + bH*(i+1)) ];
}
for (int i=0; i<bW; i++) imSeg[ (int)(indSeg[i] + bH* i) ] = 1;
}
Geoff Hayes
on 18 Jun 2019
It looks like it has been written as a mex function so I'm not all that clear on your question. Did you write the above? Or is the problem that you are trying to compile the above in MATLAB on your Mac? Please clarify.
Stelios Fanourakis
on 18 Jun 2019
@Geoff
The above code has an extension of .cpp. I need it to make it run in Matlab. I didn't write it myself. Hope that helps. I use Mac
Stelios Fanourakis
on 18 Jun 2019
I use the line
mex SegmentBone.cpp
This should do the compiling from cpp to Mex. However, I get the error
mex SegmentBoneDP.cpp
Building with 'Xcode Clang++'.
Error using mex
/Users/steliosphanourakes/Desktop/Matlab/DesMoines/karadokei -
Copy/FANOURAKIS_STELIOS12/20190516144930/SegmentBoneDP.cpp:17:17: error: assigning to 'const int *' from
incompatible type 'const mwSize *' (aka 'const unsigned long *')
DimsBness = mxGetDimensions(prhs[0]);
^~~~~~~~~~~~~~~~~~~~~~~~
/Applications/MATLAB_R2018b.app/extern/include/matrix.h:243:25: note: expanded from macro 'mxGetDimensions'
#define mxGetDimensions mxGetDimensions_730
^
/Users/steliosphanourakes/Desktop/Matlab/DesMoines/karadokei -
Copy/FANOURAKIS_STELIOS12/20190516144930/SegmentBoneDP.cpp:30:15: error: no matching function for call to
'mxCreateNumericArray_730'
plhs[0] = mxCreateNumericArray(2,DimsBness,mxDOUBLE_CLASS,mxREAL);
^~~~~~~~~~~~~~~~~~~~
/Applications/MATLAB_R2018b.app/extern/include/matrix.h:275:30: note: expanded from macro 'mxCreateNumericArray'
#define mxCreateNumericArray mxCreateNumericArray_730
^~~~~~~~~~~~~~~~~~~~~~~~
/Applications/MATLAB_R2018b.app/extern/include/matrix.h:1247:1: note: candidate function not viable: no known
conversion from 'const int *' to 'const mwSize *' (aka 'const unsigned long *') for 2nd argument
mxCreateNumericArray(mwSize ndim, const mwSize *dims, mxClassID classid, mxComplexity flag);
^
/Applications/MATLAB_R2018b.app/extern/include/matrix.h:275:30: note: expanded from macro 'mxCreateNumericArray'
#define mxCreateNumericArray mxCreateNumericArray_730
^
2 errors generated.
Anyone who can responsibly help me?
Thanks
Walter Roberson
on 18 Jun 2019
Your code has
const int *DimsBness;
That is incorrect code on 64 bit systems. It should be
const mwSize *DimsBness;
Stelios Fanourakis
on 18 Jun 2019
Walter I don't think I get it. What does this mean? I use a Macbook that does not say anywhere if it's 64 bit or not. What should I do to resolve this issue?
Walter Roberson
on 18 Jun 2019
MATLAB for 64 bit Mac was introduced in R2009b. R2010a was the last MATLAB release for 32 bit Mac. Therefore if you are running with R2010b or later on Mac, you are definitely using 64 bit version.
The official change to the API was added in R2006b https://www.mathworks.com/matlabcentral/answers/99144-how-do-i-update-mex-files-to-use-the-large-array-handling-api-largearraydims -- from then on mwSize should have been used instead of a hard-coded int data type.
If you wish to double-check then,
>> computer
ans =
'MACI64'
Notice the "64"
The C++ standard defines "int" as being "at least" 16 bits wide. https://en.cppreference.com/w/cpp/language/types . Using "int" to store the length of an array can in theory restrict the array to no more than 65535 long along any dimension. On systems that happen to use 32 bit int, using int for the size would restrict the array to 2 gigabytes (unsigned int would have at least gotten you to 4 gigabytes.)
Stelios Fanourakis
on 19 Jun 2019
Walter my system is indeed "MACI64" after applying your suggestion.
I was getting the error message that I needed to update my Xcode compiler in order to utilize the new API, that's why I used
mex -compatibleArrayDims BoneSegmentationDP.cpp
Indeed a new file BoneSegmentationDP.mexmaci64 was created succesfully in my working folder. However, it seems that I cannot do anything with it, since I cannot open it or run it. I cannot even upload it here since the Mathworks platform does not accept the extension .mexmaci64
I assume I need to adjust some parameters in the Xcode with Clang compiler that my Matlab uses to make the Mex file. I need to setup this Xcode app to export as .m files and not .mexmaci64.
Am I right?
How can I do that?
Walter Roberson
on 19 Jun 2019
You should not use -compatibleArrayDims
"I was getting the error message that I needed to update my Xcode compiler in order to utilize the new API,"
What were the error messages? Just about every mex compilation these days gives a warning message to stop using -compatibleArrayDims and rewrite code to use mwSize, but that is not an error message.
"However, it seems that I cannot do anything with it, since I cannot open it or run it."
-compatibleArrayDims is only for use on 32 bit systems.
"I cannot even upload it here since the Mathworks platform does not accept the extension .mexmaci64 "
You can zip any file and upload the zip if it is small enough. However I doubt we need the file.
"I need to setup this Xcode app to export as .m files and not .mexmaci64."
If you need that, then you are using the wrong software product. There is no known C++ to MATLAB convertor.
C++ code compiled to .mexmaci64 is directly callable from MATLAB by giving the function name, just as if it were a built-in MATLAB function.
Stelios Fanourakis
on 19 Jun 2019
Sorry Walter but I didn't understand your statement
"C++ code compiled to .mexmaci64 is directly callable from MATLAB by giving the function name, just as if it were a built-in MATLAB function."
As I said .mexmaci64 cannot be called from Matlab. By right clicking, I can make it run, however, I cannot open it to see its content for correcting its errors.
I assume the Xcode with Clang compiler that Matlab in Mac utilizes does the automated process of translating the cpp to Mex. Am I wrong?
Rik
on 19 Jun 2019
With example.mexmaci64 you can use example('input') from inside Matlab (assuming that your function takes such an input).
Stelios Fanourakis
on 20 Jun 2019
Yes. The point is that I don't know the number and type of inputs the function requires since I cannot open it to see it.
Accepted Answer
Walter Roberson
on 20 Jun 2019
Your SegmentBoneDP.cpp file is the source code.
If you need something that converts C++ code into MATLAB code, then you are using the wrong product family. There is no known program that converts C++ code into MATLAB code.
"The point is that I don't know the number and type of inputs the function requires since I cannot open it to see it. "
You read them out of the C++ source code.
Bness = (double *)mxGetData(prhs[0]);
double *pF0,*pF1,*pBth,*pJumpConst;
pF0 = (double *)mxGetData(prhs[1]);
pF1 = (double *)mxGetData(prhs[2]);
pBth = (double *)mxGetData(prhs[3]);
pJumpConst = (double *)mxGetData(prhs[4]);
The first parameter is Bness, and is a 2D double array.
The second parameter is F0, and it is a double scalar. It appears to be used as a weight or smoothing factor
The third parameter is F1, and it is a double scalar. It appears to be used as a weight or smoothing factor
The fourth parameter is Bth, and it is a double scalar. It is a threshold between bone and no bone.
The fifth parameter is JumpConst, and it is a double scalar. It appears to be some kind of penalty for moving from bone to no bone.
The output is an array the same size as Bness, and it is a real double 2D array.
More Answers (1)
Jan
on 19 Jun 2019
Edited: Jan
on 19 Jun 2019
Wow, what an inefficient communication.
As Walter has said already, the line
const int *DimsBness;
must be changed to
const mwSize *DimsBness;
This might matter other variables of the type int also.
C++ Mex files are compiled to mexmaci64 files. Of course you can neither edit these output files, not run it directly. This is the nature of compiled files. Simply put this file to a folder, which is included to your Matlab path and call it like any other function stored in an M-file:
result = BoneSegmentationDP(args)
where args are the 5 needed inputs.
"I was getting the error message that I needed to update my Xcode compiler in order to utilize the new API, that's why I used mex -compatibleArrayDims BoneSegmentationDP.cpp"
No. If you get the message, that the Xcode compiler needs an update, update the Xcode compiler. It is off-track to play around with the compatibleArrayDims flag.
8 Comments
Stelios Fanourakis
on 19 Jun 2019
Jan, how do I change the line to
const mwSize *DimsBness;
When I run this .mexmaci64 it says "Not enough input arguments".
But I cannot see its content to find out how many and what inputs to assign to it?
Furthermore, I don't see any other .m file in the folder to call this function. It seems that it is working independly.
Stelios Fanourakis
on 20 Jun 2019
I also attach both cpp and .mexmaci64 so if possible, Jan, you let me know what are the mex function's inputs.
Stelios Fanourakis
on 20 Jun 2019
Also, it seems that I cannot find the new Xcode compiler to update. The link Matlab gives me is this.
I don't understand where do I go to replace the
int nrows,ncolumns;
with
mwSize nrows,ncolumns;
If you have done this procedure Jan and can help me, that would be nice.
Thanks
Walter Roberson
on 20 Jun 2019
What leads you to think that you need to upgrade your XCode itself? The link you gave does not mention anything about that.
There was a time when XCode only supported 32 bit Executables. The XCode for Snow Leopard (OS-X 10.6, 2009) and later have supported 64 bit executables. You are using an XCode that is at least 8 years newer than that, and your XCode defaults to 64 bit.
Stelios Fanourakis
on 23 Jun 2019
Walter, I agree. I indeed use a 64 bit system since the extension using the "CompatibleArrayDims" is .mexmaci64.
However, I don't understand why when I press
mex -setup
I get the message
Warning: The MATLAB C and Fortran API has changed to support MATLAB
variables with more than 2^32-1 elements. You will be required
to update your code to utilize the new API.
You can find more information about this at:
https://www.mathworks.com/help/matlab/matlab_external/upgrading-mex-files-to-use-64-bit-api.
I don't understand the text in the link. How am I supposed to replace the following? Where do I replace them? In the C++ code?
Replace: int nrows,ncolumns;
With: mwSize nrows,ncolumns;
How is this going to make a difference? What difference?
If possible, please enlighten me.
Thanks for your assistance so far.
Walter Roberson
on 23 Jun 2019
Everyone gets that warning. It has nothing to do with you using Mac or any particular xcode version.
Walter Roberson
on 23 Jun 2019
mwSize is size_t which is unsigned long long for your system. It causes 8 bytes to be reserved for each variable that is to store an array size. That permits arrays larger than 2 gigabytes. Your existing use of int for the size is reserving only 4 bytes for array sizes.
Now you might be thinking that your particular use never involves arrays 2 gb or larger and you might be thinking that means that you do not need to use the larger variable. However 8 bytes is what matlab uses internally now and when matlab builds its internal description of the parameters to the call it is going to allocate memory based on the larger size. If your code were to try to use the sizes as if only 32 bits were allocated for the size then you would be looking for the second dimension size at the wrong place in memory.
Walter Roberson
on 23 Jun 2019
"Where do I replace them? In the C++ code?"
Yes. Edit the darn C++ code.
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list:
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)