1
- #pragma once
2
-
3
1
/*
4
- pybind11/iostream -- Tools to assist with redirecting cout and cerr to Python
2
+ pybind11/iostream.h -- Tools to assist with redirecting cout and cerr to Python
5
3
6
4
Copyright (c) 2017 Henry F. Schreiner
7
5
8
6
All rights reserved. Use of this source code is governed by a
9
7
BSD-style license that can be found in the LICENSE file.
10
8
*/
11
9
10
+ #pragma once
11
+
12
12
#include " pybind11.h"
13
13
14
14
#include < streambuf>
@@ -24,8 +24,8 @@ NAMESPACE_BEGIN(detail)
24
24
class pythonbuf : public std::streambuf {
25
25
private:
26
26
using traits_type = std::streambuf::traits_type;
27
- char d_buffer[1024 ];
28
27
28
+ char d_buffer[1024 ];
29
29
object pywrite;
30
30
object pyflush;
31
31
@@ -49,12 +49,14 @@ class pythonbuf : public std::streambuf {
49
49
}
50
50
return 0 ;
51
51
}
52
+
52
53
public:
53
54
pythonbuf (object pyostream)
54
55
: pywrite (pyostream.attr (" write" )),
55
56
pyflush (pyostream.attr (" flush" )) {
56
57
setp (d_buffer, d_buffer + sizeof (d_buffer) - 1 );
57
58
}
59
+
58
60
// / Sync before destroy
59
61
~pythonbuf () {
60
62
sync ();
@@ -65,37 +67,38 @@ NAMESPACE_END(detail)
65
67
66
68
67
69
/* * \rst
68
- Scoped ostream output redirect
69
70
This a move-only guard that redirects output.
70
71
71
72
.. code-block:: cpp
72
73
73
74
#include <pybind11/iostream.h>
74
75
75
- int main() {
76
+ ...
77
+
78
+ {
76
79
py::scoped_ostream_redirect output;
77
80
std::cout << "Hello, World!"; // Python stdout
78
81
} // <-- return std::cout to normal
79
82
80
- You can explicitly pass the c++ stream and the python object, for example to gaurd stderr instead.
83
+ You can explicitly pass the c++ stream and the python object,
84
+ for example to guard stderr instead.
81
85
82
86
.. code-block:: cpp
83
- int main() {
87
+
88
+ {
84
89
py::scoped_ostream_redirect output{std::cerr, py::module::import("sys").attr("stderr")};
85
90
std::cerr << "Hello, World!";
86
91
}
87
92
\endrst */
88
-
89
93
class scoped_ostream_redirect {
90
94
protected:
91
- std::streambuf * old;
92
- std::ostream& costream;
95
+ std::streambuf *old;
96
+ std::ostream & costream;
93
97
detail::pythonbuf buffer;
94
98
95
99
public:
96
-
97
100
scoped_ostream_redirect (
98
- std::ostream& costream = std::cout,
101
+ std::ostream & costream = std::cout,
99
102
object pyostream = module::import (" sys" ).attr (" stdout" ))
100
103
: costream (costream), buffer (pyostream) {
101
104
old = costream.rdbuf (&buffer);
@@ -113,11 +116,10 @@ class scoped_ostream_redirect {
113
116
114
117
115
118
/* * \rst
116
- Scoped ostream output redirect with cerr defaults
117
-
118
- This class is provided primary to make call_guards easier to make.
119
+ Like `scoped_ostream_redirect`, but redirects cerr by default. This class
120
+ is provided primary to make ``py::call_guard`` easier to make.
119
121
120
- .. code_block :: cpp
122
+ .. code-block :: cpp
121
123
122
124
m.def("noisy_func", &noisy_func,
123
125
py::call_guard<scoped_ostream_redirect,
@@ -127,14 +129,9 @@ class scoped_ostream_redirect {
127
129
class scoped_estream_redirect : public scoped_ostream_redirect {
128
130
public:
129
131
scoped_estream_redirect (
130
- std::ostream& costream = std::cerr,
132
+ std::ostream & costream = std::cerr,
131
133
object pyostream = module::import(" sys" ).attr(" stderr" ))
132
134
: scoped_ostream_redirect(costream,pyostream) {}
133
-
134
- scoped_estream_redirect (const scoped_estream_redirect &) = delete ;
135
- scoped_estream_redirect (scoped_estream_redirect &&other) = default ;
136
- scoped_estream_redirect &operator =(const scoped_estream_redirect &) = delete ;
137
- scoped_estream_redirect &operator =(scoped_estream_redirect &&) = delete ;
138
135
};
139
136
140
137
@@ -148,7 +145,6 @@ class OstreamRedirect {
148
145
std::unique_ptr<scoped_estream_redirect> redirect_stderr;
149
146
150
147
public:
151
-
152
148
OstreamRedirect (bool do_stdout = true , bool do_stderr = true )
153
149
: do_stdout_ (do_stdout), do_stderr_ (do_stderr) {}
154
150
@@ -168,8 +164,8 @@ class OstreamRedirect {
168
164
NAMESPACE_END (detail)
169
165
170
166
/* * \rst
171
- This is a helper function to add a C++ redirect context manager to Python instead of using a C++ guard.
172
- To use it, add the following to your binding code:
167
+ This is a helper function to add a C++ redirect context manager to Python
168
+ instead of using a C++ guard. To use it, add the following to your binding code:
173
169
174
170
.. code-block:: cpp
175
171
@@ -179,7 +175,7 @@ NAMESPACE_END(detail)
179
175
180
176
py::add_ostream_redirect(m, "ostream_redirect");
181
177
182
- You now have a python context manager that redirects your output:
178
+ You now have a Python context manager that redirects your output:
183
179
184
180
.. code-block:: python
185
181
@@ -194,16 +190,11 @@ NAMESPACE_END(detail)
194
190
m.noisy_function_with_error_printing()
195
191
196
192
\endrst */
197
-
198
193
inline class_<detail::OstreamRedirect> add_ostream_redirect(module m, std::string name = " ostream_redirect" ) {
199
- return class_<detail::OstreamRedirect>(m, name.c_str ())
194
+ return class_<detail::OstreamRedirect>(m, name.c_str (), module_local () )
200
195
.def (init<bool ,bool >(), arg (" stdout" )=true , arg (" stderr" )=true )
201
- .def (" __enter__" , [](detail::OstreamRedirect &self) {
202
- self.enter ();
203
- })
204
- .def (" __exit__" , [](detail::OstreamRedirect &self, args) {
205
- self.exit ();
206
- });
196
+ .def (" __enter__" , &detail::OstreamRedirect::enter)
197
+ .def (" __exit__" , [](detail::OstreamRedirect &self, args) { self.exit (); });
207
198
}
208
199
209
200
NAMESPACE_END (PYBIND11_NAMESPACE)
0 commit comments