I have a simple c++ class that I've built a wrapper for to interface it with python 2.7. Now, I would like to be able to call a method of that class, ExampleClass::simulate(double sim_time) through python and pause the method/thread by calling another method, ExampleClass::pause(). A very simplistic example would look something like this:
#include<iostream>
#include<unistd.h>
class ExampleClass {
public:
void simulate(double sim_time)
{
pause_ = false;
int count = 0;
while (count < 10) {
std::cout << "simulating.\n";
sleep(1);
while(pause_) {
std::cout << "paused.\n";
sleep(1);
}
count += 1;
}
}
void pause()
{
pause_ = true;
}
void resume()
{
pause_ = false;
}
private:
bool pause_;
};
With the corresponding python wrapper:
void simulate_wrapper(ExampleClass* ec, double t_sim)
{
PyGILState_STATE gstate = PyGILState_Ensure();
ec->simulate(t_sim);
PyGILState_Release(gstate);
}
BOOST_PYTHON_MODULE(ExampleExt)
{
PyEval_InitThreads();
boost::python::class_<ExampleClass>("ExampleClass")
.def("pause",&ExampleClass::pause)
.def("resume",&ExampleClass::resume)
.def("simulate", &simulate_wrapper);
}
Then in python, I have:
import threading
import time
import ExampleExt
ec = ExampleExt.ExampleClass()
t_sim = 2
def simulate(ec, t_sim):
print ('starting simulation.')
t = time.clock()
ec.simulate(t_sim)
dt = time.clock() - t
print ('simulation took',dt, 'seconds')
threading1 = threading.Thread(target=simulate, args=(ec,t_sim))
threading1.daemon = True
threading1.start()
But when I create a ExampleClass object in ipython and run the simulate function, I can't run any other commands. I was reading about GIL and apparently it blocks all python I/O events so I guess it's really not what I should be doing. Especially because I want to modify the member pause_ whilst the simulate method is running. Any thoughts on how to make this work?
Thanks
Edit: I had a go at boost::thread to see whether that would solve my problem, with some interesting results. This is how I changed my wrapper:
#include<example_class.hh>
#include<iostream>
#include<boost/python.hpp>
#include<boost/thread/thread.hpp>
#include<boost/bind.hpp>
void simulate_wrapper(ExampleClass* ec, double t_sim)
{
boost::thread t1(boost::bind(&ExampleClass::simulate,ec, t_sim));
}
And my .py script just looks like this:
import ExampleExt
ec = ExampleExt.ExampleClass()
t_sim = 2
ec.simulate(t_sim)
Everything else is the same as before. Now when I run the .py script, I can use the pause and resume methods without problems but when the simulate method finishes, I get a SIGSEGV. What could be causing it?
Thanks for any insights!