问题
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:
- Use shared
sfml
-libraries (at leastsfml-system-s
), thus the singleton will stay a singleton. - 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 forgraphics.pyx
.
来源:https://stackoverflow.com/questions/45361981/cant-redirect-error-stream-from-cython