无法从Cython重定向错误流

时间:2017-07-27 22:24:06

标签: python cython sfml iostream cythonize

我尝试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;
...

我的目标是抑制上面的错误信息出现在控制台中,最后将它们重定向到自己的缓冲区。

1 个答案:

答案 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.dllgraphics.dll,它们将在以后由python动态加载。

第二个成分:sfml - 库静态链接但包含一个单例(有问题的错误流),这是一个灾难的秘诀:使用你的设置它不再是单例,但有两种不同的错误流:来自system.dll的错误和来自graphics.dll的错误流。因此,您正在调整system.dll中的错误流(因为您的调用set_error_handler()生活在那里),但请写入graphics.dll的错误流(此处image_load_test住)。

那么可以做些什么呢?有两种选择:

  1. 使用共享sfml - 库(至少sfml-system-s),因此单身人士将保持单身人士。
  2. 将两个pyx文件的内容放在同一个pyx-file / Extension / shared库中。至少目前,system.pyx仅需要graphics.pyx的内容。