Reputation: 684
For debugging Matlab-MEX, which can be quite a hassle, it would be nice to have better assertion capabilities. Following this question about mex-assertions, it is possible to define a preprocessor makro, that throws an error to Matlab and prints a string (can mostly replace mxAssert
, which unfortunately crashes Matlab2011b).
#define myassert( isOK,astr ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(astr) )
It would be much nicer to print the file, line number and caller function, from where following example assertion myassert(A=B,"A not B")
is raised! This answer to the initial question states that they are the preprocessor variables:
__LINE__,__PRETTY_FUNCTION__, __FILE__
How can we print these preprocessor variables with mexErrMsgTxt
?
The problem is, that mexErrMsgTxt()
takes a char* argument and not multiple inputs like for example printf(const char *format, ...)
.
My thinking goes only so far at the moment:
char
from the passed string astr
and passes it to mexErrMsgTxt()
. Maybe a solution is along these lines.mexErrMsgTxt()
doesn't feel like good coding practice. It would be really nice to make the specified error string optional.
Upvotes: 1
Views: 649
Reputation: 44023
Concatenating preprocessor tokens works as long as you only use __FILE__
, __LINE__
and a string literal as message. Then you can write something like
#define STRINGIZE_I(x) #x
#define STRINGIZE(x) STRINGIZE_I(x)
#define myassert(isOK, astr) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(__FILE__ ":" STRINGIZE(__LINE__) ": " astr) )
Unfortunately, __PRETTY_FUNCTION__
is not a string literal even for those compilers who support it. If you want to use it (or less fixed error messages), you'll have to assemble the string dynamically, which means something along the lines of
#define myassert(isOK, astr) \
do { \
if(!(isOk)) { \
std::ostringstream fmt; \
fmt << "In " << __PRETTY_FUNCTION__ << ", " \
<< __FILE__ << ":" << __LINE__ << ": " << (astr); \
(void) mexErrMsgTxt(fmt.str().c_str()); \
} \
} while(false)
For C, do the same with snprintf
. (Or asprintf
. It avoids problems with fixed buffer lengths and long error messages, and it is about as portable as __PRETTY_FUNCTION__
). Either way, roughly like
#define myassert(isOK, astr) \
do { \
if(!(isOk)) { \
char buf[ENOUGH_SPACE]; \
snprintf(buf, ENOUGH_SPACE, "In %s, %s:%d: %s", \
__PRETTY_FUNCTION__, __FILE__, __LINE__, (astr)); \
buf[ENOUGH_SPACE - 1] = '\0'; \
(void) mexErrMsgTxt(buf); \
} \
} while(0)
...where ENOUGH_SPACE
would have to be defined appropriately (in the snprintf
case).
Upvotes: 3