问题
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:
- It's not possible to build a function, because the preprocessor variables will have the values (e.g. line number) from the function.
- It was not possible for me to write a working multiline preprocessor makro that creates a
char
from the passedstring astr
and passes it tomexErrMsgTxt()
. Maybe a solution is along these lines. - A hybrid solution with a char creating preprocessor makro and a function that passes it to
mexErrMsgTxt()
doesn't feel like good coding practice.
It would be really nice to make the specified error string optional.
回答1:
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).
来源:https://stackoverflow.com/questions/28630530/how-to-print-c-preprocessor-variables-like-line-with-mexerrmsgtxt-in-matla