How to print C-preprocessor variables like __LINE__ with mexErrMsgTxt() In Matlab MEX

ぃ、小莉子 提交于 2020-01-03 00:55:31

问题


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:

  1. It's not possible to build a function, because the preprocessor variables will have the values (e.g. line number) from the function.
  2. It was not possible for me to write a working multiline preprocessor makro that creates a char from the passed string astr and passes it to mexErrMsgTxt(). Maybe a solution is along these lines.
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!