MATLAB Answers

0

Compiling MEX on Win7 x64

Asked by John Reinert Nash on 2 Oct 2014
Latest activity Commented on by Walter Roberson
on 20 Sep 2015
I am attempting to compile some MEXes to run a demo of some vision science code. (https://github.com/bensapp/MODEC)
I'm running into compiler errors when doing so. I have MS Visual Studio 2010 linked as my C compiler, and I'm using MATLAB 2014a, 64bit, on Windows 7.
Error message:
features\resize.cc(36) : error C2057: expected constant expression
features\resize.cc(36) : error C2466: cannot allocate an array of constant size 0
features\resize.cc(36) : error C2133: 'ofs' : unknown size
features\resize.cc(70) : error C3861: 'bzero': identifier not found
features\resize.cc(95) : error C3861: 'round': identifier not found
features\resize.cc(96) : error C3861: 'round': identifier not found
C:\PROGRA~1\MATLAB\R2013B\BIN\MEX.PL: Error: Compile of 'features\resize.cc' failed.
if true
% code
end
Looking at other threads, it seems that some of the issue may be with a need to install the Windows SDK v7.1, but I cannot get that to install on my system correctly, from the web installer or the ISO download.
I'm attaching one of the modules I'm trying to compile, since it is short.
Advice on getting this working? Will getting Win SDK 7.1 installed likely solve the problem? Are there other 64bit compilers that may work better? Thanks in advance.
-John in Minnesota
-----resize.cc------------------------------
#include <math.h>
#include <assert.h>
#include <string.h>
#include "mex.h"
/*
* Fast image subsampling.
* This is used to construct the feature pyramid.
*/
// struct used for caching interpolation values
struct alphainfo {
int si, di;
double alpha;
};
// copy src into dst using pre-computed interpolation values
void alphacopy(double *src, double *dst, struct alphainfo *ofs, int n) {
struct alphainfo *end = ofs + n;
while (ofs != end) {
dst[ofs->di] += ofs->alpha * src[ofs->si];
ofs++;
}
}
// resize along each column
// result is transposed, so we can apply it twice for a complete resize
void resize1dtran(double *src, int sheight, double *dst, int dheight,
int width, int chan) {
double scale = (double)dheight/(double)sheight;
double invscale = (double)sheight/(double)dheight;
// we cache the interpolation values since they can be
// shared among different columns
int len = (int)ceil(dheight*invscale) + 2*dheight;
alphainfo ofs[len];
int k = 0;
for (int dy = 0; dy < dheight; dy++) {
double fsy1 = dy * invscale;
double fsy2 = fsy1 + invscale;
int sy1 = (int)ceil(fsy1);
int sy2 = (int)floor(fsy2);
if (sy1 - fsy1 > 1e-3) {
assert(k < len);
assert(sy-1 >= 0);
ofs[k].di = dy*width;
ofs[k].si = sy1-1;
ofs[k++].alpha = (sy1 - fsy1) * scale;
}
for (int sy = sy1; sy < sy2; sy++) {
assert(k < len);
assert(sy < sheight);
ofs[k].di = dy*width;
ofs[k].si = sy;
ofs[k++].alpha = scale;
}
if (fsy2 - sy2 > 1e-3) {
assert(k < len);
assert(sy2 < sheight);
ofs[k].di = dy*width;
ofs[k].si = sy2;
ofs[k++].alpha = (fsy2 - sy2) * scale;
}
}
// resize each column of each color channel
bzero(dst, chan*width*dheight*sizeof(double));
for (int c = 0; c < chan; c++) {
for (int x = 0; x < width; x++) {
double *s = src + c*width*sheight + x*sheight;
double *d = dst + c*width*dheight + x;
alphacopy(s, d, ofs, k);
}
}
}
// main function
// takes a double color image and a scaling factor
// returns resized image
mxArray *resize(const mxArray *mxsrc, const mxArray *mxscale) {
double *src = (double *)mxGetPr(mxsrc);
const int *sdims = mxGetDimensions(mxsrc);
if (mxGetNumberOfDimensions(mxsrc) != 3 ||
mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
mexErrMsgTxt("Invalid input");
double scale = mxGetScalar(mxscale);
if (scale > 1)
mexErrMsgTxt("Invalid scaling factor");
int ddims[3];
ddims[0] = (int)round(sdims[0]*scale);
ddims[1] = (int)round(sdims[1]*scale);
ddims[2] = sdims[2];
mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
double *dst = (double *)mxGetPr(mxdst);
double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
resize1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
resize1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
mxFree(tmp);
return mxdst;
}
// matlab entry point
// dst = resize(src, scale)
// image should be color with double values
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
if (nrhs != 2)
mexErrMsgTxt("Wrong number of inputs");
if (nlhs != 1)
mexErrMsgTxt("Wrong number of outputs");
plhs[0] = resize(prhs[0], prhs[1]);
}
------------------------------

  0 Comments

Sign in to comment.

2 Answers

Geoff Hayes
Answer by Geoff Hayes
on 2 Oct 2014

John - I don't have a 64-bit PC (only 32-bit) so can't comment on whether using Win SDK 7.1 will solve the problem, or whether any other compiler will. I could compile the code on my Mac, and execute the resize function with out any issues.
An alternative to trying a different compiler, and this may work depending upon how many files you have and what the errors are for each, is that you try to correct them in the code.
The first error is concerned with the line
alphainfo ofs[len];
with error C2057 described as The context requires a constant expression, an expression whose value is known at compile time (see C2057). Since the code doesn't know len at runtime, you should be able to get around this with two lines of code that allocate and free memory. Replace the above with
alphainfo* ofs = (alphainfo*)mxCalloc(len,sizeof(alphainfo));
and then add the following as the last line in resize1dtran to free the memory allocated by the MATLAB memory manager
mxFree(ofs);
That should fix the first three errors that correspond to line 36.
The next error
error C3861: 'bzero': identifier not found
corresponds to the line
bzero(dst, chan*width*dheight*sizeof(double));
which is just initializing the dst array with all zeros. Replace this with memset
memset(dst,0,chan*width*dheight*sizeof(double));
As for the final two errors
error C3861: 'round': identifier not found
which correspond to the lines
ddims[0] = (int)round(sdims[0]*scale);
ddims[1] = (int)round(sdims[1]*scale);
You could create your own round function, adding it to resize.cc as
int round(double number)
{
return (number >= 0) ? (int)(number + 0.5) : (int)(number - 0.5);
}
I made the above changes and could compile the function without problems; running resize worked as expected. These are three relatively easy fixes, but if you have to make these changes over dozens of files (fixing errors that don't correspond to these three) could prove time consuming and slightly risky.

  1 Comment

Thank you for the reply. I will try to see if I can modify the resize code to get it to compile; unfortunately, there are many other MEXes needing compilation in the package, some of which fail in various ways. I am going to attempt to install on a Mac to see I can get it to compile on that platform -- I believe the author was developing on Linux, so getting closer to Unixy things may be the trick.
Also, based on http://www.mathworks.com/matlabcentral/answers/101105-how-do-i-install-microsoft-windows-sdk-7-1, I was able to install the Windows SDK, although it did not resolve the errors. The fix entailed ripping out all of the older Visual Studio "redistributable" installs, which seem to be the source of the install issues. DLL madness....

Sign in to comment.


Answer by h612
on 20 Sep 2015

I tried fixing these. got the Mex file successfully built. But now I've an error or invalid input error at
*Error using resize Invalid input
Error in featpyramid (line 28) scaled = resize(im, 1/sc^(i-1));*

  1 Comment

Walter Roberson
on 20 Sep 2015
That would happen if your im is not 3 dimensional. The code must be passed a color image.

Sign in to comment.