Skip to content

Commit c8ae759

Browse files
author
Benjamin Chrétien
committed
ToPython: fix for multiple simultaneous instances
1 parent 9cd62b4 commit c8ae759

File tree

4 files changed

+54
-13
lines changed

4 files changed

+54
-13
lines changed

include/roboptim/core/python/to-python.hh

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace roboptim
2525
namespace python
2626
{
2727
/// \brief Helper to run Python commands in the Python interpreter.
28+
/// WARNING: this is not thread-safe for now (GIL etc.).
2829
class ToPython
2930
{
3031
public:
@@ -50,6 +51,9 @@ namespace roboptim
5051
void operator >> (std::ostream& o);
5152

5253
private:
54+
/// \brief Number of instances.
55+
static int instances_;
56+
5357
/// \brief Buffering callback.
5458
/// \param s string added to the buffer.
5559
void buffering (const std::string& s);

src/to-python.cc

+19-9
Original file line numberDiff line numberDiff line change
@@ -189,22 +189,32 @@ namespace roboptim
189189
/********************************
190190
* Implementation of ToPython *
191191
********************************/
192+
int ToPython::instances_ = 0;
192193

193194
ToPython::ToPython () : buffer_ ()
194195
{
195-
PyImport_AppendInittab ("redir", PyInit_redir);
196-
Py_Initialize ();
197-
PyImport_ImportModule ("redir");
198-
199-
// Switch sys.stdout to custom handler
200-
stdout_write_type write = boost::bind (&ToPython::buffering,
201-
this, _1);
202-
set_stdout (write);
196+
if (!instances_)
197+
{
198+
PyImport_AppendInittab ("redir", PyInit_redir);
199+
Py_Initialize ();
200+
PyImport_ImportModule ("redir");
201+
202+
// Switch sys.stdout to custom handler
203+
stdout_write_type write = boost::bind (&ToPython::buffering,
204+
this, _1);
205+
set_stdout (write);
206+
}
207+
208+
// Increment the instance counter
209+
instances_++;
203210
}
204211

205212
ToPython::~ToPython ()
206213
{
207-
Py_Exit (0);
214+
// Decrement the instance counter
215+
instances_--;
216+
217+
if (!instances_) Py_Finalize ();
208218
}
209219

210220
const ToPython& ToPython::operator << (const char* cmd) const

tests/to-python-simultaneous.stdout

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
foo
2+
bar
3+
42

tests/to-python.cc

+28-4
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
using namespace roboptim;
2525
using namespace roboptim::python;
2626

27-
boost::shared_ptr<boost::test_tools::output_test_stream> output;
27+
typedef boost::shared_ptr<boost::test_tools::output_test_stream>
28+
output_ptr;
2829

29-
BOOST_FIXTURE_TEST_SUITE (core, TestSuiteConfiguration)
30+
BOOST_AUTO_TEST_SUITE (to_python)
3031

31-
BOOST_AUTO_TEST_CASE (to_python)
32+
BOOST_AUTO_TEST_CASE (redir)
3233
{
33-
output = retrievePattern ("to-python");
34+
output_ptr output = retrievePattern ("to-python");
3435

3536
ToPython tp;
3637

@@ -53,4 +54,27 @@ BOOST_AUTO_TEST_CASE (to_python)
5354
BOOST_CHECK (output->match_pattern ());
5455
}
5556

57+
BOOST_AUTO_TEST_CASE (simultaneous)
58+
{
59+
output_ptr output = retrievePattern ("to-python-simultaneous");
60+
61+
ToPython tp1;
62+
63+
tp1 << "print(\"foo\")";
64+
65+
{
66+
ToPython tp2;
67+
tp2 << "print(\"bar\")";
68+
tp2 >> (*output);
69+
}
70+
71+
tp1 << "print(42)";
72+
73+
// Flush to output
74+
tp1 >> (*output);
75+
76+
std::cout << output->str () << std::endl;
77+
BOOST_CHECK (output->match_pattern ());
78+
}
79+
5680
BOOST_AUTO_TEST_SUITE_END ()

0 commit comments

Comments
 (0)