C++ if 语句范围内的宏未编译
C++ macro in scope of if statement not compiling
我有一些代码应该是线程安全的python/c ++ api。我正在使用宏Py_BEGIN_ALLOW_THREADS
和Py_END_ALLOW_THREADS
,它们扩展以创建保存线程状态并创建锁。我在方法退出之前释放锁;一次在语句作用域内if
一次,一次在方法作用域内。
为什么这不编译?它会生成错误:error: _save was not declared in this scope
第二个Py_END_ALLOW_THREADS
宏。
uint8_t SerialBuffer::push_msg() {
#if defined (UBUNTU)
Py_BEGIN_ALLOW_THREADS
#endif
if (_type == ARRAY) {
// array access
} else if (_type == PRIORITY_QUEUE) {
// queue access
} else {
// Placing the return statement in the preprocessor directive
// has no effect.
#if defined (UBUNTU)
Py_END_ALLOW_THREADS
#endif
return FAIL;
}
#if defined (UBUNTU)
Py_END_ALLOW_THREADS
#endif
return SUCCESS;
}
我还尝试将return
语句放在#if
指令范围内,这会产生相同的错误。但是,这有效:
uint8_t SerialBuffer::push_msg() {
#if defined (UBUNTU)
Py_BEGIN_ALLOW_THREADS
#endif
if (_type == ARRAY) {
// array access
} else if (_type == PRIORITY_QUEUE) {
// queue access
} else {
// NOTE lack of #if directive here.
// Even though if this code executes the code below will not.
// Seems like a relatively simple problem for lambda calculus, no?
return FAIL;
}
#if defined (UBUNTU)
Py_END_ALLOW_THREADS
#endif
return SUCCESS;
}
编辑:我知道第二个示例不进行线程清理;但是,它会编译。
编辑2:Py_BEGIN_ALLOW_THREADS
扩展到{ PyThreadState *_save; _save = PyEval_SaveThread();
Py_END_ALLOW_THREADS
扩展到PyEval_RestoreThread(_save); }
请注意,范围大括号在前面加上BEGIN
,并附加END
。为什么宏扩展包含范围是合乎逻辑的选择?
预处理器将宏Py_BEGIN_ALLOW_THREADS
展开为创建名为_save
的本地对象的代码。
预处理器将宏Py_END_ALLOW_THREADS
扩展为使用_save
执行线程清理任务的代码。
如果将Py_BEGIN_ALLOW_THREADS
放在 else 块中,则Py_END_ALLOW_THREADS
创建的代码看不到本地_save
对象,因此会收到错误消息。
在相关主题上,我建议将Py_BEGIN_ALLOW_THREADS
和Py_END_ALLOW_THREADS
放在如果第一个执行的位置,那么第二个执行。如果您有数组类型或优先级队列类型,则函数的第二个版本不会执行Py_END_ALLOW_THREADS
线程清理任务。
试试这个:
uint8_t SerialBuffer::push_msg() {
#if defined (UBUNTU)
Py_BEGIN_ALLOW_THREADS
#endif
uint8_t response = FAIL;
if (_type == ARRAY) {
// array access
response = SUCCESS;
} else if (_type == PRIORITY_QUEUE) {
// queue access
response = SUCCESS;
}
#if defined (UBUNTU)
Py_END_ALLOW_THREADS
#endif
return response;
}
在此版本中,默认响应是 FAIL,因此您甚至不需要最后的 else 部分。另一个 if 语句仅在一切顺利时设置 SUCCESS 的响应。
来自 [Python.Docs]:初始化、终结和线程 - Py_BEGIN_ALLOW_THREADS(重点是我的(:
此宏扩展到
{ PyThreadState *_save; _save = PyEval_SaveThread();
.请注意,它包含一个左大括号;它必须与以下Py_END_ALLOW_THREADS宏匹配。有关此宏的进一步讨论,请参见上文。
因此,编译错误的答案非常明确:
-
预处理后,第 2Py_END_ALLOW_THREADS生成无效代码(并且
#if defined (UBUNTU)
中的封闭无关紧要,因为它在定义UBUNTU时永远不会工作,而在未定义时它将始终有效(:- 引用(不存在(">_save"
- 一个额外的右大括号 (">}"(
上页还举例说明了 2 个宏的常见用例:
PyThreadState *_save; _save = PyEval_SaveThread(); ... Do some blocking I/O operation ... PyEval_RestoreThread(_save);
为什么以这种方式设计(包括范围(?像你一样使用时可能会失败,因为这可能会导致难以找到错误(你的示例非常简单,但是在一个更复杂的代码中,许多分支需要同样多的Py_END_ALLOW_THREADS,想象一下错过一个意味着什么,或者调用它两次(。
为了解决您的问题,您必须重新设计您的代码,以便:
- 不是在失败时直接返回,而是标记它,在最后返回(在一个地方(,并在返回之前放置Py_END_ALLOW_THREADS
- 调用每个(或在需要时(if分支(ARRAY,PRIORITY_QUEUE,...(中的宏对
- 使用(可怕的(转到
- 为什么在全局范围内使用"extern int a"似乎不行?
- C++ 在编译过程中 strtok 函数 Eclipse 说没有在范围内声明?
- C++ if 语句范围内的宏未编译
- 在 mingw64- 变量下的窗口中编译 openvpn3 时出错,未在范围内声明
- 非命名空间范围内的显式专用化不会在 GCC 中编译
- 编译错误 在 C++ 上,Calcarea 未在此范围内声明
- 试图过渡到GTK3(针对GTK -3.0库编译)时,在此范围内未声明GTK_Object
- 代码块编译错误.Cin 未在此范围内声明
- 编译 gsoap-onvif 求解 #error:M_ASN1_STRING_data“未在此范围内声明
- 编译错误:..在此范围内未声明
- 针对 android 编译的问题..."未在此范围内声明"错误
- arm-none-eabi-g++ 编译器抛出编译错误pthread_exit未在此范围内声明
- 如何检查函数是否在编译时在全局范围内声明
- C++代码块 |我在编译时不断收到相同的消息" .......未在范围内声明。如何在范围内声明某些内容?
- 用clang编译MSVC std库.在类范围内显式的模板函数特化
- NDK 编译错误:未在此范围内声明'stod'
- 通过build_native.py返回编译 cocos2d-x:"to_string"未在此范围内声明
- 在 Cygwin 中编译:'EOF'没有在此范围内声明,在 CentOS 中编译得很好
- 尝试编译的新手:有些未在此范围内声明
- 在编译时检查指定的值是否在类型的范围内