如何在 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, ...)
。
目前我的想法就到此为止了:
- 无法构建函数,因为预处理器变量将具有函数中的值(例如行号)。
- 我无法编写一个工作的多行预处理器宏,从传递的
string astr
中创建一个 char
并将其传递给 mexErrMsgTxt()
。 Maybe a solution is along these lines.
- 混合 解决方案,其中包含创建预处理器 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
情况下)。
对于调试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, ...)
。
目前我的想法就到此为止了:
- 无法构建函数,因为预处理器变量将具有函数中的值(例如行号)。
- 我无法编写一个工作的多行预处理器宏,从传递的
string astr
中创建一个char
并将其传递给mexErrMsgTxt()
。 Maybe a solution is along these lines. - 混合 解决方案,其中包含创建预处理器 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
情况下)。