我尝试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;
...
我的目标是抑制上面的错误信息出现在控制台中,最后将它们重定向到自己的缓冲区。
答案 0 :(得分:1)
您的问题有两个要素,两者都在您的设置文件中。
第一个要素是你有两个扩展名:
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
),因此单身人士将保持单身人士。system.pyx
仅需要graphics.pyx
的内容。