Can't redirect error stream from Cython

笑着哭i 提交于 2019-12-12 22:21:23

问题


The SFML library that I'm trying to cythonize defines this function below that allows to change where errors are printed to (by default SFML writes error messages to the console when this function is not called):

namespace sf {
    std::ostream& err() {
        static DefaultErrStreamBuf buffer;
        static std::ostream stream(&buffer);
        return stream;
    }
}

My simplified .pxd file for the above function:

cdef extern from 'SFML/System.hpp' namespace 'sf':
    ostream& cerr 'sf::err' ()

And my .pyx module, which compiles and runs fine, but doesn't redirect the error messages (they are still printed to the console).

cdef void set_error_handler():
    cerr().rdbuf(NULL)  # This call should prevent errors appearing in the console but it silently fails

set_error_handler()

I'm using MSVC and linking statically with the C++ code.

Edit

Below is example how the SFML library logs errors in its own code (full source):

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

My goal is to suppress the error messages like the one above from appearing in the console and eventually later redirect them into own buffer.


回答1:


There are two ingredients for your problem and both are in your setup-file.

The first ingredient is that you have two extensions:

ext_modules = [
    Extension('nebula.sfml.system', ['nebula/sfml/system.pyx'],
              language='c++', ...),
    Extension('nebula.sfml.graphics', ['nebula/sfml/graphics.pyx'],
              language='c++', ...),
] 

that means cython will create two different shared libraries: system.dll and graphics.dll which will be both loaded later on dynamically by python.

The second ingredient: the sfml-library is linked statically but contains a singleton (the error-stream in question) and this is a recipe for disaster: With your set-up it is no longer a singleton, but there are two different error-streams: The one from system.dll and the one from graphics.dll. So you are silencing the error-stream from the system.dll (because your call set_error_handler() lives there), but write to the error-stream from the graphics.dll (this where image_load_test lives).

So what can be done? There are two options:

  1. Use shared sfml-libraries (at least sfml-system-s), thus the singleton will stay a singleton.
  2. Put the content of both pyx-files in the same pyx-file/Extension/shared library. At least right now, the content of system.pyx is only needed for graphics.pyx.


来源:https://stackoverflow.com/questions/45361981/cant-redirect-error-stream-from-cython

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!