Reputation: 4650
I'm currently using a mex function where integers are sent as a parameter by first converting it to int
type with:
a = int32(10);
foo(a);
Where foo receives/checks a
by using:
void get_integer_scalar(int &scalar,const mxArray *mat_buf) {
// Check input
if (mxIsClass(mat_buf,"int32")) {
if (mxGetN(mat_buf) == 1 && mxGetM(mat_buf) == 1) {
// At this point, input is correct
scalar = *((int *)mxGetData(mat_buf));
} else {
mexErrMsgTxt("Integer scalar is not of size == [1 1].\n");
}
} else {
mexErrMsgTxt("Integer scalar is not int32.\n");
}
}
Now, it just sort of dawned upon me that the int
type is machine dependent, so the line scalar = *((int *)mxGetData(mat_buf));
might be unsafe (or is it? I'm trying to not make assumptions about how int32()
works in matlab). Is there a safe way to pass a standard int
type to a mex file or should I be using a 32 bit int type like int32_t
?
Upvotes: 2
Views: 5638
Reputation: 30579
Use mxGetScalar
, which returns a double value, no matter what the input type, which you can cast without worry.
double mxGetScalar(const mxArray *pm); // the type of data in pm doesn't matter
In C,
mxGetScalar
returns a double. If real elements in themxArray
are of a type other thandouble
,mxGetScalar
automatically converts the scalar value into adouble
. To preserve the original data representation of the scalar, cast the return value to the desired data type.
Just check the number of elements, and you don't even need a type check (but I would use mxIsInt32
for that, if needed):
#include <mex.h>
void get_integer_scalar(int &scalar,const mxArray *mat_buf) {
// Check input
if (!mxIsInt32(mat_buf))
mexPrintf("Integer scalar is not int32, but that's OK.\n");
if (mxGetNumberOfElements(mat_buf) == 1) {
scalar = mxGetScalar(mat_buf);
} else {
mexErrMsgTxt("Integer scalar is not of size == [1 1].\n");
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int val;
if (nrhs>0)
{
get_integer_scalar(val,prhs[0]); // type of prhs[0] does not matter
mexPrintf("%d\n",val);
}
}
To answer your question, MATLAB's int32
is obviously not machine dependent, but as you pointed out there are no guarantees that C++ int
will be 32-bit. I think mxGetScalar
addresses this for scalars, but for arrays (when you need a pointer safely casted) I think you are right that you can use <stdint.h>
or <cstdint>
, which set int8_t
, int16_t
, int32_t
, int64_t
, etc. Visual Studio does typedef int int32_t;
.
MATLAB also has a header for this purpose: tmwtypes.h
. It sets the following fixed-width types:
/*=======================================================================*
* Fixed width word size data types: *
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
* real32_T, real64_T - 32 and 64 bit floating point numbers *
*=======================================================================*/
And here's the relevant piece for int32_T
:
#ifndef INT32_T
# if TMW_BITS_PER_INT == 32
# define INT32_T int
# elif TMW_BITS_PER_LONG == 32
# define INT32_T long
# elif TMW_BITS_PER_SCHAR == 32
# define INT32_T signed char
# elif TMW_BITS_PER_SHRT == 32
# define INT32_T short
# endif
#endif
#ifdef INT32_T
typedef INT32_T int32_T;
#endif
It gets TMW_BITS_PER_INT
earlier in the header by comparing INT_MAX
with various hexadecimal literals, and 0x7FFFFFFFL
wins out. Basically, you can use int32_T
, as described in the docs for mxClassID
, if you are including tmwtypes.h
.
However, I doubt MATLAB supports any tool set that uses anything but a 32-bit unsigned integer for int
.
Upvotes: 4