如何在 Matlab MEX 中使用 mexErrMsgTxt() 打印像 __LINE__ 这样的 C 预处理器变量

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

对于调试Matlab-MEX,这可能是一件很麻烦的事情,如果有更好的断言能力就好了。在 this question about mex-assertions 之后,可以定义一个预处理器 makro,它会向 Matlab 抛出一个错误并打印一个字符串(主要可以替换 mxAssert,不幸的是它会导致 Matlab2011b 崩溃)。

#define myassert( isOK,astr )      ( (isOK) ? (void)0 : (void) mexErrMsgTxt(astr) ) 

打印文件、行号和调用函数会更好,下面的示例断言 myassert(A=B,"A not B") 就是从这里引发的! This answer 对最初的问题指出它们是预处理器变量:

__LINE__,__PRETTY_FUNCTION__, __FILE__

我们如何使用 mexErrMsgTxt 打印这些预处理器变量?

问题是,mexErrMsgTxt() 采用一个 char* 参数,而不是多个输入,例如 printf(const char *format, ...)

目前我的想法就到此为止了:

  1. 无法构建函数,因为预处理器变量将具有函数中的值(例如行号)。
  2. 我无法编写一个工作的多行预处理器宏,从传递的 string astr 中创建一个 char 并将其传递给 mexErrMsgTxt()Maybe a solution is along these lines.
  3. 混合 解决方案,其中包含创建预处理器 makro 的字符和将其传递给 mexErrMsgTxt() 的函数,感觉不像是良好的编码习惯。

如果能将指定的错误字符串设为可选,那就太好了。

只要您仅使用 __FILE____LINE__ 和字符串文字作为消息,连接预处理器标记就可以工作。然后你可以这样写

#define STRINGIZE_I(x) #x
#define STRINGIZE(x) STRINGIZE_I(x)

#define myassert(isOK, astr) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(__FILE__ ":" STRINGIZE(__LINE__) ": " astr) )

不幸的是,即使对于那些支持它的编译器来说,__PRETTY_FUNCTION__ 也不是字符串文字。如果你想使用它(或更少的固定错误消息),你必须动态地 assemble 字符串,这意味着类似于

#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)

对于 C,对 snprintf 执行相同的操作。 (或 asprintf。它避免了固定缓冲区长度和长错误消息的问题,并且它与 __PRETTY_FUNCTION__ 一样可移植)。无论哪种方式,大致像

#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] = '[=12=]';                                     \
      (void) mexErrMsgTxt(buf);                                         \
    }                                                                   \
  } while(0)

...其中 ENOUGH_SPACE 必须适当定义(在 snprintf 情况下)。