Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
586 views
in Technique[技术] by (71.8m points)

python - Can't redirect error stream from Cython

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...