1

我试图 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 库如何在自己的代码中记录错误的示例(完整源代码):

...
// Error, failed to load the image
err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl;
...

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

4

1 回答 1

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-library 是静态链接的,但包含一个单例(有问题的错误流),这是灾难的根源:通过您的设置,它不再是单例,但有两个不同的错误流: 一个来自system.dll一个来自graphics.dllsystem.dll因此,您正在使来自(因为您的呼叫set_error_handler()存在)的错误流静音,但从graphics.dll(在此存在)写入错误流image_load_test

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

  1. 使用共享sfml库(至少sfml-system-s),因此单例将保持单例。
  2. 将两个 pyx 文件的内容放在同一个 pyx 文件/扩展/共享库中。至少现在, 的内容system.pyx只需要graphics.pyx.
于 2017-07-28T11:26:22.073 回答