无法从 Cython 重定向错误流
Can't redirect error stream from Cython
我尝试使用 cythonize 的 SFML 库在下面定义了这个函数,它允许更改打印错误的位置(默认情况下,SFML 在未调用此函数时将错误消息写入控制台):
namespace sf {
std::ostream& err() {
static DefaultErrStreamBuf buffer;
static std::ostream stream(&buffer);
return stream;
}
}
我为上述功能简化的 .pxd 文件:
cdef extern from 'SFML/System.hpp' namespace 'sf':
ostream& cerr 'sf::err' ()
还有我的 .pyx 模块,它可以正常编译和运行,但不会重定向错误消息(它们仍会打印到控制台)。
cdef void set_error_handler():
cerr().rdbuf(NULL) # This call should prevent errors appearing in the console but it silently fails
set_error_handler()
我正在使用 MSVC 并静态链接到 C++ 代码。
编辑
下面是 SFML 库如何在自己的代码中记录错误的示例 (full source):
...
// Error, failed to load the image
err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl;
...
我的目标是抑制类似上述的错误消息出现在控制台中,并最终将它们重定向到自己的缓冲区中。
您的问题有两种成分,它们都在您的设置文件中。
第一个要素是你有两个扩展:
ext_modules = [
Extension('nebula.sfml.system', ['nebula/sfml/system.pyx'],
language='c++', ...),
Extension('nebula.sfml.graphics', ['nebula/sfml/graphics.pyx'],
language='c++', ...),
]
这意味着 cython 将创建两个不同的共享库:system.dll
和 graphics.dll
稍后将由 python.
动态加载
第二个要素:sfml
-库是静态链接的,但包含一个单例(有问题的错误流),这是灾难的根源:有了你的设置,它不再是一个单例,但有两种不同的错误流:一种来自 system.dll
,另一种来自 graphics.dll
。因此,您要从 system.dll
中消除错误流(因为您的调用 set_error_handler()
存在于此),但是从 graphics.dll
写入错误流(此处 image_load_test
生命)。
那么可以做什么呢?有两种选择:
- 使用共享
sfml
-库(至少 sfml-system-s
),因此单例将保持单例。
- 将两个 pyx 文件的内容放在同一个 pyx-file/Extension/shared 库中。至少现在
system.pyx
的内容只需要 graphics.pyx
.
我尝试使用 cythonize 的 SFML 库在下面定义了这个函数,它允许更改打印错误的位置(默认情况下,SFML 在未调用此函数时将错误消息写入控制台):
namespace sf {
std::ostream& err() {
static DefaultErrStreamBuf buffer;
static std::ostream stream(&buffer);
return stream;
}
}
我为上述功能简化的 .pxd 文件:
cdef extern from 'SFML/System.hpp' namespace 'sf':
ostream& cerr 'sf::err' ()
还有我的 .pyx 模块,它可以正常编译和运行,但不会重定向错误消息(它们仍会打印到控制台)。
cdef void set_error_handler():
cerr().rdbuf(NULL) # This call should prevent errors appearing in the console but it silently fails
set_error_handler()
我正在使用 MSVC 并静态链接到 C++ 代码。
编辑
下面是 SFML 库如何在自己的代码中记录错误的示例 (full source):
...
// Error, failed to load the image
err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl;
...
我的目标是抑制类似上述的错误消息出现在控制台中,并最终将它们重定向到自己的缓冲区中。
您的问题有两种成分,它们都在您的设置文件中。
第一个要素是你有两个扩展:
ext_modules = [
Extension('nebula.sfml.system', ['nebula/sfml/system.pyx'],
language='c++', ...),
Extension('nebula.sfml.graphics', ['nebula/sfml/graphics.pyx'],
language='c++', ...),
]
这意味着 cython 将创建两个不同的共享库:system.dll
和 graphics.dll
稍后将由 python.
第二个要素:sfml
-库是静态链接的,但包含一个单例(有问题的错误流),这是灾难的根源:有了你的设置,它不再是一个单例,但有两种不同的错误流:一种来自 system.dll
,另一种来自 graphics.dll
。因此,您要从 system.dll
中消除错误流(因为您的调用 set_error_handler()
存在于此),但是从 graphics.dll
写入错误流(此处 image_load_test
生命)。
那么可以做什么呢?有两种选择:
- 使用共享
sfml
-库(至少sfml-system-s
),因此单例将保持单例。 - 将两个 pyx 文件的内容放在同一个 pyx-file/Extension/shared 库中。至少现在
system.pyx
的内容只需要graphics.pyx
.