MATLAB Answers

0

MEX passing Integer - wrong results

Asked by mbvoyager on 14 Nov 2017
Latest activity Edited by Jan
on 13 Nov 2019 at 12:17
Hello,
I have a C++ code that I try to embed in Matlab using a mex function. Everything worked just fine, till I tried to hand over integers from Matlab.
Suppose I call my Mex function like:
myMexFun(0.1, 0.1, 30, 4000);
Apparently it makes a difference if I use: (1)
int a = (int)*mxGetPr(prhs[3]);
instead of defining it directly in my C++ code with: (2)
int a = 4000;
Since the first (1) expression will yield very far off wrong results.
a is used for all calculating operations (+,-,*,/) as well as an index for arrays.
Additionally I am doing the very same thing with a smaller integer for another parameter prhs[2] - (range 5-150) and with this input I do not get any issues.
What am I overseeing here?
Kind regards, and thanks for your time.

  2 Comments

Jan
on 14 Nov 2017
Please post the relevant part of the code. Especially a description like "I am doing the very same thing with a smaller integer" is not useful to reconsider, what the problem is.
int a
a = (int) *mxGetPr(prhs[3]);
Should work. I'd prefer:
a = (int) mxGetScalar(prhs[0]);
because then you can use inputs of any type also. Perhaps the 4000 you are providing is a int32 in Matlab?
The problem looks like this:
a=4000;
b=30;
myMexFun(0.1, 0.1, b, a);
What works totally fine is:
int b = (int)*mxGetPr(prhs[2]);
But what yields wrong results if I implement it is:
int a = (int)*mxGetPr(prhs[3]);
The changes you suggested yield the same results.
b and a are part of numerous calculations with all operands as well as used for indices, also they are casted to doubles. With the Number b I have no issues, all results are fine. But when I use the second integer input a and try to hand it over from matlab, results get messy. The double values are also not causing any damage.
I also cleared the memory and everything in between different runs, but the problem still persists.
Also if I write something like:
a = int32(4000);
Matlab just crashes during the C++ function.
Thank you for your time.

Sign in to comment.

2 Answers

Jan
Answer by Jan
on 14 Nov 2017
Edited by Jan
on 13 Nov 2019 at 12:17

This sounds magic. Whenever magic things appear in discussions in the forum, or at programming in general, it is a secure signal, that the author has overseen an important detail. To find the source of the problem, create a MWE: Minimal working example.
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int a = (int) *mxGetPr(prhs[3]); // Better: *mxGetData(prhs[3])
mexPrintf("%i\n", a);
mexPrintf("%g\n", (double) a);
mexPrintf("%g\n", mxGetScalar(prhs[3]));
}
Try it. I expect, that the correct values are displayed. This would mean, that perhaps your observation is wrong: How do you find out, that the value of a differs from your expectations? Maybe this test is the only problem.

  3 Comments

Clearly I have overseen something.
the MMW works fine. I try to further narrow the problem. The thing is the code is pretty complex and I've not written it.
But I see now that at some point I get a different result for an array. Please don't close this thread. I will try to identify the exact problem and code line where "the magic happens".
It smells like the handling of indices in some for loops is somewhat different.
Case (1) - fixed declaration:
Calling Function:
myMexFun(0.1, 0.1, 30);
yields
const int a = 4000;
a - 1:
mexPrintf("%i\n", a); --> 4000
mexPrintf("%g\n", (double) a); --> 4000
mexPrintf("%g\n", mxGetScalar(prhs[3])); --> 0
NumOfStepProb - 2:
int NumOfStepProb=(int)(10*a);
mexPrintf("%i\n", NumOfStepProb); --> 40000
mexPrintf("%g\n", (double) NumOfStepProb); --> 40000
xg[a]-3:
double xg[a+1];
[...350 lines of code and 12 for loops later ...]
mexPrintf("%g\n", xg[a]); --> 2.54068
mexPrintf("%g\n", (double) xg[a]); --> 2.54068
-------------------------------------------------------------
Which is correct!
Case (2) - Matlab Input handle:
Calling Function:
myMexFun(0.1, 0.1, 30, 4000);
yields:
const int a = (int)*mxGetPr(prhs[3]);
a - 1:
mexPrintf("%i\n", a); --> 4000
mexPrintf("%g\n", (double) a); --> 4000
mexPrintf("%g\n", mxGetScalar(prhs[3])); --> 4000
NumOfStepProb - 2:
int NumOfStepProb=(int)(10*a);
mexPrintf("%i\n", NumOfStepProb); --> 40000
mexPrintf("%g\n", (double) NumOfStepProb); --> 40000
xg[a]-3:
double xg[a+1];
[...350 lines of code and 12 for loops later ...]
mexPrintf("%g\n", xg[a]); --> 40000
mexPrintf("%g\n", (double) xg[a]); --> 40000
-------------------------------------------------------------
Which is wrong!
Thank you really much for your time! I appreciate it.
Aloha lei,
first of all, I still don't have the final solution but I am coming closer to it. I guess/hope.
It looks like I was using different compiler versions. A few weeks ago I started upgrading all my code and the compiler to the Visual Studio 2017 C++ compiler in order to be able to use the Visual Studio IDE for my Mex-Function debugging.
I notice that some initialization behaviour of arrays has changed.
So far it looks like that sometimes an initialized array, contained weird values. Which makes sense in C++.
But sometimes those arrays weren't fully filled with new values and so the code accessed those weird values.
Additionally, with the new compiler version, I get the error that some integers which I am passing through the Matlab mex function are not constant and therefore not usable as array size declarators. This leads right back to the lines where I am actually saving the passed values using the mex arrays.
double Threshold = mxGetScalar(prhs[0]);
double deltat = mxGetScalar(prhs[1]);
int BoundN = (int)*mxGetPr(prhs[2]);
This is exactly the line which I've mentioned at the beginning of this thread. But now I get the error message that BoundN needs to be constant. The mxArray prhs[], in fact, is constant which can be seen here
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
but the value passed from calling my Mex-Function seems to be not.
If I delete the assignment and declare the value BoundN "manually"
const int BoundN = 120;
The compiler throws no errors.
I can not declare BoundN as const in the assignment because the value out of *prhs[] is not constant.
I am considering now two things.
  1. Don't pass BoundN, which is a solution I could live with but certainly is not very nice.
  2. Use std::vector and try where I can get with it.
So probably this magic that happened is because of the different compilers I've used (I've used also different Matlab versions) and also a bunch of errors that I've not identified yet.
Because on another machine sometimes the code works fine and also new changes and compilations work fine. But it's like 1 out of 10....
Jan
on 29 Aug 2018
In your former comment (link) you write: "Which is wrong!" I still do not have any idea about what you consider as wrong here. Without seeing the code, it is impossible to find the cause of the problem. Therefore I can only guess, that an uninitialized pointer is used anywhere.
"sometimes those arrays weren't fully filled with new values" - please elaborate this.
"with the new compiler version, I get the error that some integers which I am passing through the Matlab mex function are not constant" - Please post the specific line and a copy of the error message. The problem is not, that the integer is not constant, but that the variable is not declared as const. So what about casting it to const?

Sign in to comment.


Answer by Nope
on 13 Nov 2019 at 8:05

From what I understand, mxGetPr() always returns the pointer as type mxDOUBLE_CLASS*. If you pass an integer the typecasting in this line:
const int a = (int)*mxGetPr(prhs[3]);
should interpret your integer as a double and then convert that interpretation to an integer.

  0 Comments

Sign in to comment.